summaryrefslogtreecommitdiffstats
path: root/arch/sparc/include/asm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/include/asm')
-rw-r--r--arch/sparc/include/asm/Kbuild6
-rw-r--r--arch/sparc/include/asm/adi.h6
-rw-r--r--arch/sparc/include/asm/adi_64.h46
-rw-r--r--arch/sparc/include/asm/apb.h37
-rw-r--r--arch/sparc/include/asm/asm-offsets.h1
-rw-r--r--arch/sparc/include/asm/asm-prototypes.h25
-rw-r--r--arch/sparc/include/asm/asm.h41
-rw-r--r--arch/sparc/include/asm/asmmacro.h46
-rw-r--r--arch/sparc/include/asm/atomic.h9
-rw-r--r--arch/sparc/include/asm/atomic_32.h61
-rw-r--r--arch/sparc/include/asm/atomic_64.h73
-rw-r--r--arch/sparc/include/asm/auxio.h16
-rw-r--r--arch/sparc/include/asm/auxio_32.h89
-rw-r--r--arch/sparc/include/asm/auxio_64.h99
-rw-r--r--arch/sparc/include/asm/backoff.h86
-rw-r--r--arch/sparc/include/asm/barrier.h9
-rw-r--r--arch/sparc/include/asm/barrier_32.h7
-rw-r--r--arch/sparc/include/asm/barrier_64.h61
-rw-r--r--arch/sparc/include/asm/bbc.h226
-rw-r--r--arch/sparc/include/asm/bitext.h28
-rw-r--r--arch/sparc/include/asm/bitops.h9
-rw-r--r--arch/sparc/include/asm/bitops_32.h108
-rw-r--r--arch/sparc/include/asm/bitops_64.h63
-rw-r--r--arch/sparc/include/asm/btext.h7
-rw-r--r--arch/sparc/include/asm/bug.h30
-rw-r--r--arch/sparc/include/asm/cache.h26
-rw-r--r--arch/sparc/include/asm/cacheflush.h13
-rw-r--r--arch/sparc/include/asm/cacheflush_32.h62
-rw-r--r--arch/sparc/include/asm/cacheflush_64.h82
-rw-r--r--arch/sparc/include/asm/cachetlb_32.h30
-rw-r--r--arch/sparc/include/asm/chafsr.h242
-rw-r--r--arch/sparc/include/asm/checksum.h12
-rw-r--r--arch/sparc/include/asm/checksum_32.h210
-rw-r--r--arch/sparc/include/asm/checksum_64.h144
-rw-r--r--arch/sparc/include/asm/chmctrl.h184
-rw-r--r--arch/sparc/include/asm/clock.h11
-rw-r--r--arch/sparc/include/asm/clocksource.h17
-rw-r--r--arch/sparc/include/asm/cmpxchg.h9
-rw-r--r--arch/sparc/include/asm/cmpxchg_32.h80
-rw-r--r--arch/sparc/include/asm/cmpxchg_64.h208
-rw-r--r--arch/sparc/include/asm/compat.h160
-rw-r--r--arch/sparc/include/asm/compat_signal.h24
-rw-r--r--arch/sparc/include/asm/contregs.h32
-rw-r--r--arch/sparc/include/asm/cpu_type.h29
-rw-r--r--arch/sparc/include/asm/cpudata.h19
-rw-r--r--arch/sparc/include/asm/cpudata_32.h32
-rw-r--r--arch/sparc/include/asm/cpudata_64.h42
-rw-r--r--arch/sparc/include/asm/current.h35
-rw-r--r--arch/sparc/include/asm/dcr.h15
-rw-r--r--arch/sparc/include/asm/dcu.h28
-rw-r--r--arch/sparc/include/asm/delay.h9
-rw-r--r--arch/sparc/include/asm/delay_32.h35
-rw-r--r--arch/sparc/include/asm/delay_64.h18
-rw-r--r--arch/sparc/include/asm/device.h29
-rw-r--r--arch/sparc/include/asm/dma-mapping.h13
-rw-r--r--arch/sparc/include/asm/dma.h92
-rw-r--r--arch/sparc/include/asm/ebus_dma.h36
-rw-r--r--arch/sparc/include/asm/ecc.h123
-rw-r--r--arch/sparc/include/asm/eeprom.h9
-rw-r--r--arch/sparc/include/asm/elf.h9
-rw-r--r--arch/sparc/include/asm/elf_32.h132
-rw-r--r--arch/sparc/include/asm/elf_64.h232
-rw-r--r--arch/sparc/include/asm/estate.h50
-rw-r--r--arch/sparc/include/asm/extable.h21
-rw-r--r--arch/sparc/include/asm/fb.h41
-rw-r--r--arch/sparc/include/asm/fbio.h73
-rw-r--r--arch/sparc/include/asm/fhc.h81
-rw-r--r--arch/sparc/include/asm/floppy.h9
-rw-r--r--arch/sparc/include/asm/floppy_32.h393
-rw-r--r--arch/sparc/include/asm/floppy_64.h779
-rw-r--r--arch/sparc/include/asm/fpumacro.h34
-rw-r--r--arch/sparc/include/asm/ftrace.h34
-rw-r--r--arch/sparc/include/asm/futex.h9
-rw-r--r--arch/sparc/include/asm/futex_32.h6
-rw-r--r--arch/sparc/include/asm/futex_64.h94
-rw-r--r--arch/sparc/include/asm/hardirq.h9
-rw-r--r--arch/sparc/include/asm/hardirq_32.h13
-rw-r--r--arch/sparc/include/asm/hardirq_64.h19
-rw-r--r--arch/sparc/include/asm/head.h9
-rw-r--r--arch/sparc/include/asm/head_32.h84
-rw-r--r--arch/sparc/include/asm/head_64.h81
-rw-r--r--arch/sparc/include/asm/hibernate.h24
-rw-r--r--arch/sparc/include/asm/highmem.h61
-rw-r--r--arch/sparc/include/asm/hugetlb.h60
-rw-r--r--arch/sparc/include/asm/hvtramp.h38
-rw-r--r--arch/sparc/include/asm/hw_irq.h6
-rw-r--r--arch/sparc/include/asm/hypervisor.h3527
-rw-r--r--arch/sparc/include/asm/idprom.h26
-rw-r--r--arch/sparc/include/asm/intr_queue.h16
-rw-r--r--arch/sparc/include/asm/io-unit.h59
-rw-r--r--arch/sparc/include/asm/io.h24
-rw-r--r--arch/sparc/include/asm/io_32.h153
-rw-r--r--arch/sparc/include/asm/io_64.h481
-rw-r--r--arch/sparc/include/asm/ioctls.h14
-rw-r--r--arch/sparc/include/asm/iommu-common.h53
-rw-r--r--arch/sparc/include/asm/iommu.h9
-rw-r--r--arch/sparc/include/asm/iommu_32.h122
-rw-r--r--arch/sparc/include/asm/iommu_64.h93
-rw-r--r--arch/sparc/include/asm/irq.h9
-rw-r--r--arch/sparc/include/asm/irq_32.h24
-rw-r--r--arch/sparc/include/asm/irq_64.h98
-rw-r--r--arch/sparc/include/asm/irqflags.h9
-rw-r--r--arch/sparc/include/asm/irqflags_32.h48
-rw-r--r--arch/sparc/include/asm/irqflags_64.h98
-rw-r--r--arch/sparc/include/asm/jump_label.h52
-rw-r--r--arch/sparc/include/asm/kdebug.h9
-rw-r--r--arch/sparc/include/asm/kdebug_32.h75
-rw-r--r--arch/sparc/include/asm/kdebug_64.h24
-rw-r--r--arch/sparc/include/asm/kgdb.h42
-rw-r--r--arch/sparc/include/asm/kprobes.h57
-rw-r--r--arch/sparc/include/asm/ldc.h149
-rw-r--r--arch/sparc/include/asm/leon.h266
-rw-r--r--arch/sparc/include/asm/leon_amba.h267
-rw-r--r--arch/sparc/include/asm/leon_pci.h23
-rw-r--r--arch/sparc/include/asm/lsu.h20
-rw-r--r--arch/sparc/include/asm/machines.h51
-rw-r--r--arch/sparc/include/asm/mbus.h97
-rw-r--r--arch/sparc/include/asm/mc146818rtc.h14
-rw-r--r--arch/sparc/include/asm/mc146818rtc_32.h30
-rw-r--r--arch/sparc/include/asm/mc146818rtc_64.h29
-rw-r--r--arch/sparc/include/asm/mdesc.h99
-rw-r--r--arch/sparc/include/asm/memctrl.h10
-rw-r--r--arch/sparc/include/asm/mman.h91
-rw-r--r--arch/sparc/include/asm/mmu.h9
-rw-r--r--arch/sparc/include/asm/mmu_32.h11
-rw-r--r--arch/sparc/include/asm/mmu_64.h129
-rw-r--r--arch/sparc/include/asm/mmu_context.h9
-rw-r--r--arch/sparc/include/asm/mmu_context_32.h34
-rw-r--r--arch/sparc/include/asm/mmu_context_64.h198
-rw-r--r--arch/sparc/include/asm/mmzone.h18
-rw-r--r--arch/sparc/include/asm/mxcc.h138
-rw-r--r--arch/sparc/include/asm/nmi.h14
-rw-r--r--arch/sparc/include/asm/ns87303.h118
-rw-r--r--arch/sparc/include/asm/obio.h226
-rw-r--r--arch/sparc/include/asm/openprom.h280
-rw-r--r--arch/sparc/include/asm/oplib.h9
-rw-r--r--arch/sparc/include/asm/oplib_32.h184
-rw-r--r--arch/sparc/include/asm/oplib_64.h252
-rw-r--r--arch/sparc/include/asm/page.h12
-rw-r--r--arch/sparc/include/asm/page_32.h138
-rw-r--r--arch/sparc/include/asm/page_64.h163
-rw-r--r--arch/sparc/include/asm/parport.h256
-rw-r--r--arch/sparc/include/asm/pbm.h48
-rw-r--r--arch/sparc/include/asm/pci.h44
-rw-r--r--arch/sparc/include/asm/pcic.h130
-rw-r--r--arch/sparc/include/asm/pcr.h51
-rw-r--r--arch/sparc/include/asm/percpu.h9
-rw-r--r--arch/sparc/include/asm/percpu_32.h7
-rw-r--r--arch/sparc/include/asm/percpu_64.h27
-rw-r--r--arch/sparc/include/asm/perf_event.h30
-rw-r--r--arch/sparc/include/asm/pgalloc.h9
-rw-r--r--arch/sparc/include/asm/pgalloc_32.h77
-rw-r--r--arch/sparc/include/asm/pgalloc_64.h118
-rw-r--r--arch/sparc/include/asm/pgtable.h9
-rw-r--r--arch/sparc/include/asm/pgtable_32.h441
-rw-r--r--arch/sparc/include/asm/pgtable_64.h1181
-rw-r--r--arch/sparc/include/asm/pgtsrmmu.h141
-rw-r--r--arch/sparc/include/asm/pil.h31
-rw-r--r--arch/sparc/include/asm/processor.h9
-rw-r--r--arch/sparc/include/asm/processor_32.h100
-rw-r--r--arch/sparc/include/asm/processor_64.h247
-rw-r--r--arch/sparc/include/asm/prom.h59
-rw-r--r--arch/sparc/include/asm/psr.h68
-rw-r--r--arch/sparc/include/asm/ptrace.h162
-rw-r--r--arch/sparc/include/asm/qrwlock.h8
-rw-r--r--arch/sparc/include/asm/qspinlock.h8
-rw-r--r--arch/sparc/include/asm/ross.h192
-rw-r--r--arch/sparc/include/asm/sbi.h116
-rw-r--r--arch/sparc/include/asm/scratchpad.h15
-rw-r--r--arch/sparc/include/asm/seccomp.h11
-rw-r--r--arch/sparc/include/asm/sections.h14
-rw-r--r--arch/sparc/include/asm/setup.h72
-rw-r--r--arch/sparc/include/asm/sfafsr.h83
-rw-r--r--arch/sparc/include/asm/sfp-machine.h9
-rw-r--r--arch/sparc/include/asm/sfp-machine_32.h212
-rw-r--r--arch/sparc/include/asm/sfp-machine_64.h93
-rw-r--r--arch/sparc/include/asm/shmparam.h9
-rw-r--r--arch/sparc/include/asm/shmparam_32.h10
-rw-r--r--arch/sparc/include/asm/shmparam_64.h11
-rw-r--r--arch/sparc/include/asm/sigcontext.h109
-rw-r--r--arch/sparc/include/asm/signal.h17
-rw-r--r--arch/sparc/include/asm/smp.h9
-rw-r--r--arch/sparc/include/asm/smp_32.h130
-rw-r--r--arch/sparc/include/asm/smp_64.h86
-rw-r--r--arch/sparc/include/asm/sparsemem.h14
-rw-r--r--arch/sparc/include/asm/spinlock.h9
-rw-r--r--arch/sparc/include/asm/spinlock_32.h188
-rw-r--r--arch/sparc/include/asm/spinlock_64.h19
-rw-r--r--arch/sparc/include/asm/spinlock_types.h25
-rw-r--r--arch/sparc/include/asm/spitfire.h368
-rw-r--r--arch/sparc/include/asm/stacktrace.h7
-rw-r--r--arch/sparc/include/asm/starfire.h20
-rw-r--r--arch/sparc/include/asm/string.h47
-rw-r--r--arch/sparc/include/asm/string_32.h15
-rw-r--r--arch/sparc/include/asm/string_64.h15
-rw-r--r--arch/sparc/include/asm/sunbpp.h81
-rw-r--r--arch/sparc/include/asm/swift.h107
-rw-r--r--arch/sparc/include/asm/switch_to.h9
-rw-r--r--arch/sparc/include/asm/switch_to_32.h107
-rw-r--r--arch/sparc/include/asm/switch_to_64.h71
-rw-r--r--arch/sparc/include/asm/syscall.h132
-rw-r--r--arch/sparc/include/asm/syscalls.h11
-rw-r--r--arch/sparc/include/asm/termbits.h9
-rw-r--r--arch/sparc/include/asm/thread_info.h9
-rw-r--r--arch/sparc/include/asm/thread_info_32.h130
-rw-r--r--arch/sparc/include/asm/thread_info_64.h242
-rw-r--r--arch/sparc/include/asm/timer.h9
-rw-r--r--arch/sparc/include/asm/timer_32.h45
-rw-r--r--arch/sparc/include/asm/timer_64.h98
-rw-r--r--arch/sparc/include/asm/timex.h9
-rw-r--r--arch/sparc/include/asm/timex_32.h14
-rw-r--r--arch/sparc/include/asm/timex_64.h20
-rw-r--r--arch/sparc/include/asm/tlb.h9
-rw-r--r--arch/sparc/include/asm/tlb_32.h7
-rw-r--r--arch/sparc/include/asm/tlb_64.h38
-rw-r--r--arch/sparc/include/asm/tlbflush.h9
-rw-r--r--arch/sparc/include/asm/tlbflush_32.h25
-rw-r--r--arch/sparc/include/asm/tlbflush_64.h71
-rw-r--r--arch/sparc/include/asm/topology.h9
-rw-r--r--arch/sparc/include/asm/topology_32.h7
-rw-r--r--arch/sparc/include/asm/topology_64.h65
-rw-r--r--arch/sparc/include/asm/trap_block.h217
-rw-r--r--arch/sparc/include/asm/traps.h25
-rw-r--r--arch/sparc/include/asm/tsb.h380
-rw-r--r--arch/sparc/include/asm/tsunami.h65
-rw-r--r--arch/sparc/include/asm/ttable.h694
-rw-r--r--arch/sparc/include/asm/turbosparc.h126
-rw-r--r--arch/sparc/include/asm/uaccess.h15
-rw-r--r--arch/sparc/include/asm/uaccess_32.h220
-rw-r--r--arch/sparc/include/asm/uaccess_64.h252
-rw-r--r--arch/sparc/include/asm/unistd.h63
-rw-r--r--arch/sparc/include/asm/upa.h110
-rw-r--r--arch/sparc/include/asm/uprobes.h47
-rw-r--r--arch/sparc/include/asm/user.h6
-rw-r--r--arch/sparc/include/asm/vaddrs.h71
-rw-r--r--arch/sparc/include/asm/vdso.h22
-rw-r--r--arch/sparc/include/asm/vga.h60
-rw-r--r--arch/sparc/include/asm/viking.h255
-rw-r--r--arch/sparc/include/asm/vio.h512
-rw-r--r--arch/sparc/include/asm/visasm.h67
-rw-r--r--arch/sparc/include/asm/vmalloc.h4
-rw-r--r--arch/sparc/include/asm/vvar.h75
-rw-r--r--arch/sparc/include/asm/winmacro.h132
-rw-r--r--arch/sparc/include/asm/xor.h9
-rw-r--r--arch/sparc/include/asm/xor_32.h268
-rw-r--r--arch/sparc/include/asm/xor_64.h79
246 files changed, 24222 insertions, 0 deletions
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
new file mode 100644
index 000000000..43b0ae4c2
--- /dev/null
+++ b/arch/sparc/include/asm/Kbuild
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+generated-y += syscall_table_32.h
+generated-y += syscall_table_64.h
+generic-y += agp.h
+generic-y += kvm_para.h
+generic-y += mcs_spinlock.h
diff --git a/arch/sparc/include/asm/adi.h b/arch/sparc/include/asm/adi.h
new file mode 100644
index 000000000..acad0d04e
--- /dev/null
+++ b/arch/sparc/include/asm/adi.h
@@ -0,0 +1,6 @@
+#ifndef ___ASM_SPARC_ADI_H
+#define ___ASM_SPARC_ADI_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/adi_64.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/adi_64.h b/arch/sparc/include/asm/adi_64.h
new file mode 100644
index 000000000..4301c6fd8
--- /dev/null
+++ b/arch/sparc/include/asm/adi_64.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* adi_64.h: ADI related data structures
+ *
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ * Author: Khalid Aziz (khalid.aziz@oracle.com)
+ */
+#ifndef __ASM_SPARC64_ADI_H
+#define __ASM_SPARC64_ADI_H
+
+#include <linux/types.h>
+
+#ifndef __ASSEMBLY__
+
+struct adi_caps {
+ __u64 blksz;
+ __u64 nbits;
+ __u64 ue_on_adi;
+};
+
+struct adi_config {
+ bool enabled;
+ struct adi_caps caps;
+};
+
+extern struct adi_config adi_state;
+
+extern void mdesc_adi_init(void);
+
+static inline bool adi_capable(void)
+{
+ return adi_state.enabled;
+}
+
+static inline unsigned long adi_blksize(void)
+{
+ return adi_state.caps.blksz;
+}
+
+static inline unsigned long adi_nbits(void)
+{
+ return adi_state.caps.nbits;
+}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* !(__ASM_SPARC64_ADI_H) */
diff --git a/arch/sparc/include/asm/apb.h b/arch/sparc/include/asm/apb.h
new file mode 100644
index 000000000..b1dfb1a99
--- /dev/null
+++ b/arch/sparc/include/asm/apb.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * apb.h: Advanced PCI Bridge Configuration Registers and Bits
+ *
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef _SPARC64_APB_H
+#define _SPARC64_APB_H
+
+#define APB_TICK_REGISTER 0xb0
+#define APB_INT_ACK 0xb8
+#define APB_PRIMARY_MASTER_RETRY_LIMIT 0xc0
+#define APB_DMA_ASFR 0xc8
+#define APB_DMA_AFAR 0xd0
+#define APB_PIO_TARGET_RETRY_LIMIT 0xd8
+#define APB_PIO_TARGET_LATENCY_TIMER 0xd9
+#define APB_DMA_TARGET_RETRY_LIMIT 0xda
+#define APB_DMA_TARGET_LATENCY_TIMER 0xdb
+#define APB_SECONDARY_MASTER_RETRY_LIMIT 0xdc
+#define APB_SECONDARY_CONTROL 0xdd
+#define APB_IO_ADDRESS_MAP 0xde
+#define APB_MEM_ADDRESS_MAP 0xdf
+
+#define APB_PCI_CONTROL_LOW 0xe0
+# define APB_PCI_CTL_LOW_ARB_PARK (1 << 21)
+# define APB_PCI_CTL_LOW_ERRINT_EN (1 << 8)
+
+#define APB_PCI_CONTROL_HIGH 0xe4
+# define APB_PCI_CTL_HIGH_SERR (1 << 2)
+# define APB_PCI_CTL_HIGH_ARBITER_EN (1 << 0)
+
+#define APB_PIO_ASFR 0xe8
+#define APB_PIO_AFAR 0xf0
+#define APB_DIAG_REGISTER 0xf8
+
+#endif /* !(_SPARC64_APB_H) */
diff --git a/arch/sparc/include/asm/asm-offsets.h b/arch/sparc/include/asm/asm-offsets.h
new file mode 100644
index 000000000..d370ee36a
--- /dev/null
+++ b/arch/sparc/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/sparc/include/asm/asm-prototypes.h b/arch/sparc/include/asm/asm-prototypes.h
new file mode 100644
index 000000000..4987c735f
--- /dev/null
+++ b/arch/sparc/include/asm/asm-prototypes.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <asm/xor.h>
+#include <asm/checksum.h>
+#include <asm/trap_block.h>
+#include <linux/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/ftrace.h>
+#include <asm/cacheflush.h>
+#include <asm/oplib.h>
+#include <linux/atomic.h>
+
+void *__memscan_zero(void *, size_t);
+void *__memscan_generic(void *, int, size_t);
+void *__bzero(void *, size_t);
+void VISenter(void); /* Dummy prototype to supress warning */
+#undef memcpy
+#undef memset
+void *memcpy(void *dest, const void *src, size_t n);
+void *memset(void *s, int c, size_t n);
+typedef int TItype __attribute__((mode(TI)));
+TItype __multi3(TItype a, TItype b);
diff --git a/arch/sparc/include/asm/asm.h b/arch/sparc/include/asm/asm.h
new file mode 100644
index 000000000..eaed0117a
--- /dev/null
+++ b/arch/sparc/include/asm/asm.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_ASM_H
+#define _SPARC_ASM_H
+
+/* Macros to assist the sharing of assembler code between 32-bit and
+ * 64-bit sparc.
+ */
+
+#ifdef CONFIG_SPARC64
+#define BRANCH32(TYPE, PREDICT, DEST) \
+ TYPE,PREDICT %icc, DEST
+#define BRANCH32_ANNUL(TYPE, PREDICT, DEST) \
+ TYPE,a,PREDICT %icc, DEST
+#define BRANCH_REG_ZERO(PREDICT, REG, DEST) \
+ brz,PREDICT REG, DEST
+#define BRANCH_REG_ZERO_ANNUL(PREDICT, REG, DEST) \
+ brz,a,PREDICT REG, DEST
+#define BRANCH_REG_NOT_ZERO(PREDICT, REG, DEST) \
+ brnz,PREDICT REG, DEST
+#define BRANCH_REG_NOT_ZERO_ANNUL(PREDICT, REG, DEST) \
+ brnz,a,PREDICT REG, DEST
+#else
+#define BRANCH32(TYPE, PREDICT, DEST) \
+ TYPE DEST
+#define BRANCH32_ANNUL(TYPE, PREDICT, DEST) \
+ TYPE,a DEST
+#define BRANCH_REG_ZERO(PREDICT, REG, DEST) \
+ cmp REG, 0; \
+ be DEST
+#define BRANCH_REG_ZERO_ANNUL(PREDICT, REG, DEST) \
+ cmp REG, 0; \
+ be,a DEST
+#define BRANCH_REG_NOT_ZERO(PREDICT, REG, DEST) \
+ cmp REG, 0; \
+ bne DEST
+#define BRANCH_REG_NOT_ZERO_ANNUL(PREDICT, REG, DEST) \
+ cmp REG, 0; \
+ bne,a DEST
+#endif
+
+#endif /* _SPARC_ASM_H */
diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h
new file mode 100644
index 000000000..49aaf6f3b
--- /dev/null
+++ b/arch/sparc/include/asm/asmmacro.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* asmmacro.h: Assembler macros.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
+ */
+
+#ifndef _SPARC_ASMMACRO_H
+#define _SPARC_ASMMACRO_H
+
+/* All trap entry points _must_ begin with this macro or else you
+ * lose. It makes sure the kernel has a proper window so that
+ * c-code can be called.
+ */
+#define SAVE_ALL_HEAD \
+ sethi %hi(trap_setup), %l4; \
+ jmpl %l4 + %lo(trap_setup), %l6;
+#define SAVE_ALL \
+ SAVE_ALL_HEAD \
+ nop;
+
+/* All traps low-level code here must end with this macro. */
+#define RESTORE_ALL b ret_trap_entry; clr %l6;
+
+/* Support for run-time patching of single instructions.
+ * This is used to handle the differences in the ASI for
+ * MMUREGS for LEON and SUN.
+ *
+ * Sample:
+ * LEON_PI(lda [%g0] ASI_LEON_MMUREGS, %o0
+ * SUN_PI_(lda [%g0] ASI_M_MMUREGS, %o0
+ * PI == Patch Instruction
+ *
+ * For LEON we will use the first variant,
+ * and for all other we will use the SUN variant.
+ * The order is important.
+ */
+#define LEON_PI(...) \
+662: __VA_ARGS__
+
+#define SUN_PI_(...) \
+ .section .leon_1insn_patch, "ax"; \
+ .word 662b; \
+ __VA_ARGS__; \
+ .previous
+
+#endif /* !(_SPARC_ASMMACRO_H) */
diff --git a/arch/sparc/include/asm/atomic.h b/arch/sparc/include/asm/atomic.h
new file mode 100644
index 000000000..425151cc4
--- /dev/null
+++ b/arch/sparc/include/asm/atomic.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_ATOMIC_H
+#define ___ASM_SPARC_ATOMIC_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/atomic_64.h>
+#else
+#include <asm/atomic_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h
new file mode 100644
index 000000000..60ce2fe57
--- /dev/null
+++ b/arch/sparc/include/asm/atomic_32.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* atomic.h: These still suck, but the I-cache hit rate is higher.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
+ *
+ * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
+ * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
+ */
+
+#ifndef __ARCH_SPARC_ATOMIC__
+#define __ARCH_SPARC_ATOMIC__
+
+#include <linux/types.h>
+
+#include <asm/cmpxchg.h>
+#include <asm/barrier.h>
+#include <asm-generic/atomic64.h>
+
+int arch_atomic_add_return(int, atomic_t *);
+#define arch_atomic_add_return arch_atomic_add_return
+
+int arch_atomic_fetch_add(int, atomic_t *);
+#define arch_atomic_fetch_add arch_atomic_fetch_add
+
+int arch_atomic_fetch_and(int, atomic_t *);
+#define arch_atomic_fetch_and arch_atomic_fetch_and
+
+int arch_atomic_fetch_or(int, atomic_t *);
+#define arch_atomic_fetch_or arch_atomic_fetch_or
+
+int arch_atomic_fetch_xor(int, atomic_t *);
+#define arch_atomic_fetch_xor arch_atomic_fetch_xor
+
+int arch_atomic_cmpxchg(atomic_t *, int, int);
+#define arch_atomic_cmpxchg arch_atomic_cmpxchg
+
+int arch_atomic_xchg(atomic_t *, int);
+#define arch_atomic_xchg arch_atomic_xchg
+
+int arch_atomic_fetch_add_unless(atomic_t *, int, int);
+#define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless
+
+void arch_atomic_set(atomic_t *, int);
+
+#define arch_atomic_set_release(v, i) arch_atomic_set((v), (i))
+
+#define arch_atomic_read(v) READ_ONCE((v)->counter)
+
+#define arch_atomic_add(i, v) ((void)arch_atomic_add_return( (int)(i), (v)))
+#define arch_atomic_sub(i, v) ((void)arch_atomic_add_return(-(int)(i), (v)))
+
+#define arch_atomic_and(i, v) ((void)arch_atomic_fetch_and((i), (v)))
+#define arch_atomic_or(i, v) ((void)arch_atomic_fetch_or((i), (v)))
+#define arch_atomic_xor(i, v) ((void)arch_atomic_fetch_xor((i), (v)))
+
+#define arch_atomic_sub_return(i, v) (arch_atomic_add_return(-(int)(i), (v)))
+#define arch_atomic_fetch_sub(i, v) (arch_atomic_fetch_add (-(int)(i), (v)))
+
+#endif /* !(__ARCH_SPARC_ATOMIC__) */
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h
new file mode 100644
index 000000000..a5e9c3760
--- /dev/null
+++ b/arch/sparc/include/asm/atomic_64.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* atomic.h: Thankfully the V9 is at least reasonable for this
+ * stuff.
+ *
+ * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __ARCH_SPARC64_ATOMIC__
+#define __ARCH_SPARC64_ATOMIC__
+
+#include <linux/types.h>
+#include <asm/cmpxchg.h>
+#include <asm/barrier.h>
+
+#define ATOMIC64_INIT(i) { (i) }
+
+#define arch_atomic_read(v) READ_ONCE((v)->counter)
+#define arch_atomic64_read(v) READ_ONCE((v)->counter)
+
+#define arch_atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
+#define arch_atomic64_set(v, i) WRITE_ONCE(((v)->counter), (i))
+
+#define ATOMIC_OP(op) \
+void arch_atomic_##op(int, atomic_t *); \
+void arch_atomic64_##op(s64, atomic64_t *);
+
+#define ATOMIC_OP_RETURN(op) \
+int arch_atomic_##op##_return(int, atomic_t *); \
+s64 arch_atomic64_##op##_return(s64, atomic64_t *);
+
+#define ATOMIC_FETCH_OP(op) \
+int arch_atomic_fetch_##op(int, atomic_t *); \
+s64 arch_atomic64_fetch_##op(s64, atomic64_t *);
+
+#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_OP_RETURN(op) ATOMIC_FETCH_OP(op)
+
+ATOMIC_OPS(add)
+ATOMIC_OPS(sub)
+
+#define arch_atomic_add_return arch_atomic_add_return
+#define arch_atomic_sub_return arch_atomic_sub_return
+#define arch_atomic_fetch_add arch_atomic_fetch_add
+#define arch_atomic_fetch_sub arch_atomic_fetch_sub
+
+#define arch_atomic64_add_return arch_atomic64_add_return
+#define arch_atomic64_sub_return arch_atomic64_sub_return
+#define arch_atomic64_fetch_add arch_atomic64_fetch_add
+#define arch_atomic64_fetch_sub arch_atomic64_fetch_sub
+
+#undef ATOMIC_OPS
+#define ATOMIC_OPS(op) ATOMIC_OP(op) ATOMIC_FETCH_OP(op)
+
+ATOMIC_OPS(and)
+ATOMIC_OPS(or)
+ATOMIC_OPS(xor)
+
+#define arch_atomic_fetch_and arch_atomic_fetch_and
+#define arch_atomic_fetch_or arch_atomic_fetch_or
+#define arch_atomic_fetch_xor arch_atomic_fetch_xor
+
+#define arch_atomic64_fetch_and arch_atomic64_fetch_and
+#define arch_atomic64_fetch_or arch_atomic64_fetch_or
+#define arch_atomic64_fetch_xor arch_atomic64_fetch_xor
+
+#undef ATOMIC_OPS
+#undef ATOMIC_FETCH_OP
+#undef ATOMIC_OP_RETURN
+#undef ATOMIC_OP
+
+s64 arch_atomic64_dec_if_positive(atomic64_t *v);
+#define arch_atomic64_dec_if_positive arch_atomic64_dec_if_positive
+
+#endif /* !(__ARCH_SPARC64_ATOMIC__) */
diff --git a/arch/sparc/include/asm/auxio.h b/arch/sparc/include/asm/auxio.h
new file mode 100644
index 000000000..a2681052e
--- /dev/null
+++ b/arch/sparc/include/asm/auxio.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_AUXIO_H
+#define ___ASM_SPARC_AUXIO_H
+
+#ifndef __ASSEMBLY__
+
+extern void __iomem *auxio_register;
+
+#endif /* ifndef __ASSEMBLY__ */
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/auxio_64.h>
+#else
+#include <asm/auxio_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/auxio_32.h b/arch/sparc/include/asm/auxio_32.h
new file mode 100644
index 000000000..852457c7a
--- /dev/null
+++ b/arch/sparc/include/asm/auxio_32.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * auxio.h: Definitions and code for the Auxiliary I/O register.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_AUXIO_H
+#define _SPARC_AUXIO_H
+
+#include <asm/vaddrs.h>
+
+/* This register is an unsigned char in IO space. It does two things.
+ * First, it is used to control the front panel LED light on machines
+ * that have it (good for testing entry points to trap handlers and irq's)
+ * Secondly, it controls various floppy drive parameters.
+ */
+#define AUXIO_ORMEIN 0xf0 /* All writes must set these bits. */
+#define AUXIO_ORMEIN4M 0xc0 /* sun4m - All writes must set these bits. */
+#define AUXIO_FLPY_DENS 0x20 /* Floppy density, high if set. Read only. */
+#define AUXIO_FLPY_DCHG 0x10 /* A disk change occurred. Read only. */
+#define AUXIO_EDGE_ON 0x10 /* sun4m - On means Jumper block is in. */
+#define AUXIO_FLPY_DSEL 0x08 /* Drive select/start-motor. Write only. */
+#define AUXIO_LINK_TEST 0x08 /* sun4m - On means TPE Carrier detect. */
+
+/* Set the following to one, then zero, after doing a pseudo DMA transfer. */
+#define AUXIO_FLPY_TCNT 0x04 /* Floppy terminal count. Write only. */
+
+/* Set the following to zero to eject the floppy. */
+#define AUXIO_FLPY_EJCT 0x02 /* Eject floppy disk. Write only. */
+#define AUXIO_LED 0x01 /* On if set, off if unset. Read/Write */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * NOTE: these routines are implementation dependent--
+ * understand the hardware you are querying!
+ */
+void set_auxio(unsigned char bits_on, unsigned char bits_off);
+unsigned char get_auxio(void); /* .../asm/floppy.h */
+
+/*
+ * The following routines are provided for driver-compatibility
+ * with sparc64 (primarily sunlance.c)
+ */
+
+#define AUXIO_LTE_ON 1
+#define AUXIO_LTE_OFF 0
+
+/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
+ *
+ * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
+ */
+#define auxio_set_lte(on) \
+do { \
+ if(on) { \
+ set_auxio(AUXIO_LINK_TEST, 0); \
+ } else { \
+ set_auxio(0, AUXIO_LINK_TEST); \
+ } \
+} while (0)
+
+#define AUXIO_LED_ON 1
+#define AUXIO_LED_OFF 0
+
+/* auxio_set_led - Set system front panel LED
+ *
+ * on - AUXIO_LED_ON or AUXIO_LED_OFF
+ */
+#define auxio_set_led(on) \
+do { \
+ if(on) { \
+ set_auxio(AUXIO_LED, 0); \
+ } else { \
+ set_auxio(0, AUXIO_LED); \
+ } \
+} while (0)
+
+#endif /* !(__ASSEMBLY__) */
+
+
+/* AUXIO2 (Power Off Control) */
+extern volatile u8 __iomem *auxio_power_register;
+
+#define AUXIO_POWER_DETECT_FAILURE 32
+#define AUXIO_POWER_CLEAR_FAILURE 2
+#define AUXIO_POWER_OFF 1
+
+
+#endif /* !(_SPARC_AUXIO_H) */
diff --git a/arch/sparc/include/asm/auxio_64.h b/arch/sparc/include/asm/auxio_64.h
new file mode 100644
index 000000000..ae1ed4198
--- /dev/null
+++ b/arch/sparc/include/asm/auxio_64.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * auxio.h: Definitions and code for the Auxiliary I/O registers.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net)
+ */
+#ifndef _SPARC64_AUXIO_H
+#define _SPARC64_AUXIO_H
+
+/* AUXIO implementations:
+ * sbus-based NCR89C105 "Slavio"
+ * LED/Floppy (AUX1) register
+ * Power (AUX2) register
+ *
+ * ebus-based auxio on PCIO
+ * LED Auxio Register
+ * Power Auxio Register
+ *
+ * Register definitions from NCR _NCR89C105 Chip Specification_
+ *
+ * SLAVIO AUX1 @ 0x1900000
+ * -------------------------------------------------
+ * | (R) | (R) | D | (R) | E | M | T | L |
+ * -------------------------------------------------
+ * (R) - bit 7:6,4 are reserved and should be masked in s/w
+ * D - Floppy Density Sense (1=high density) R/O
+ * E - Link Test Enable, directly reflected on AT&T 7213 LTE pin
+ * M - Monitor/Mouse Mux, directly reflected on MON_MSE_MUX pin
+ * T - Terminal Count: sends TC pulse to 82077 floppy controller
+ * L - System LED on front panel (0=off, 1=on)
+ */
+#define AUXIO_AUX1_MASK 0xc0 /* Mask bits */
+#define AUXIO_AUX1_FDENS 0x20 /* Floppy Density Sense */
+#define AUXIO_AUX1_LTE 0x08 /* Link Test Enable */
+#define AUXIO_AUX1_MMUX 0x04 /* Monitor/Mouse Mux */
+#define AUXIO_AUX1_FTCNT 0x02 /* Terminal Count, */
+#define AUXIO_AUX1_LED 0x01 /* System LED */
+
+/* SLAVIO AUX2 @ 0x1910000
+ * -------------------------------------------------
+ * | (R) | (R) | D | (R) | (R) | (R) | C | F |
+ * -------------------------------------------------
+ * (R) - bits 7:6,4:2 are reserved and should be masked in s/w
+ * D - Power Failure Detect (1=power fail)
+ * C - Clear Power Failure Detect Int (1=clear)
+ * F - Power Off (1=power off)
+ */
+#define AUXIO_AUX2_MASK 0xdc /* Mask Bits */
+#define AUXIO_AUX2_PFAILDET 0x20 /* Power Fail Detect */
+#define AUXIO_AUX2_PFAILCLR 0x02 /* Clear Pwr Fail Det Intr */
+#define AUXIO_AUX2_PWR_OFF 0x01 /* Power Off */
+
+/* Register definitions from Sun Microsystems _PCIO_ p/n 802-7837
+ *
+ * PCIO LED Auxio @ 0x726000
+ * -------------------------------------------------
+ * | 31:1 Unused | LED |
+ * -------------------------------------------------
+ * Bits 31:1 unused
+ * LED - System LED on front panel (0=off, 1=on)
+ */
+#define AUXIO_PCIO_LED 0x01 /* System LED */
+
+/* PCIO Power Auxio @ 0x724000
+ * -------------------------------------------------
+ * | 31:2 Unused | CPO | SPO |
+ * -------------------------------------------------
+ * Bits 31:2 unused
+ * CPO - Courtesy Power Off (1=off)
+ * SPO - System Power Off (1=off)
+ */
+#define AUXIO_PCIO_CPWR_OFF 0x02 /* Courtesy Power Off */
+#define AUXIO_PCIO_SPWR_OFF 0x01 /* System Power Off */
+
+#ifndef __ASSEMBLY__
+
+#define AUXIO_LTE_ON 1
+#define AUXIO_LTE_OFF 0
+
+/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
+ *
+ * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
+ */
+void auxio_set_lte(int on);
+
+#define AUXIO_LED_ON 1
+#define AUXIO_LED_OFF 0
+
+/* auxio_set_led - Set system front panel LED
+ *
+ * on - AUXIO_LED_ON or AUXIO_LED_OFF
+ */
+void auxio_set_led(int on);
+
+#endif /* ifndef __ASSEMBLY__ */
+
+#endif /* !(_SPARC64_AUXIO_H) */
diff --git a/arch/sparc/include/asm/backoff.h b/arch/sparc/include/asm/backoff.h
new file mode 100644
index 000000000..597a22953
--- /dev/null
+++ b/arch/sparc/include/asm/backoff.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_BACKOFF_H
+#define _SPARC64_BACKOFF_H
+
+/* The macros in this file implement an exponential backoff facility
+ * for atomic operations.
+ *
+ * When multiple threads compete on an atomic operation, it is
+ * possible for one thread to be continually denied a successful
+ * completion of the compare-and-swap instruction. Heavily
+ * threaded cpu implementations like Niagara can compound this
+ * problem even further.
+ *
+ * When an atomic operation fails and needs to be retried, we spin a
+ * certain number of times. At each subsequent failure of the same
+ * operation we double the spin count, realizing an exponential
+ * backoff.
+ *
+ * When we spin, we try to use an operation that will cause the
+ * current cpu strand to block, and therefore make the core fully
+ * available to any other runnable strands. There are two
+ * options, based upon cpu capabilities.
+ *
+ * On all cpus prior to SPARC-T4 we do three dummy reads of the
+ * condition code register. Each read blocks the strand for something
+ * between 40 and 50 cpu cycles.
+ *
+ * For SPARC-T4 and later we have a special "pause" instruction
+ * available. This is implemented using writes to register %asr27.
+ * The cpu will block the number of cycles written into the register,
+ * unless a disrupting trap happens first. SPARC-T4 specifically
+ * implements pause with a granularity of 8 cycles. Each strand has
+ * an internal pause counter which decrements every 8 cycles. So the
+ * chip shifts the %asr27 value down by 3 bits, and writes the result
+ * into the pause counter. If a value smaller than 8 is written, the
+ * chip blocks for 1 cycle.
+ *
+ * To achieve the same amount of backoff as the three %ccr reads give
+ * on earlier chips, we shift the backoff value up by 7 bits. (Three
+ * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the
+ * whole amount we want to block into the pause register, rather than
+ * loop writing 128 each time.
+ */
+
+#define BACKOFF_LIMIT (4 * 1024)
+
+#ifdef CONFIG_SMP
+
+#define BACKOFF_SETUP(reg) \
+ mov 1, reg
+
+#define BACKOFF_LABEL(spin_label, continue_label) \
+ spin_label
+
+#define BACKOFF_SPIN(reg, tmp, label) \
+ mov reg, tmp; \
+88: rd %ccr, %g0; \
+ rd %ccr, %g0; \
+ rd %ccr, %g0; \
+ .section .pause_3insn_patch,"ax";\
+ .word 88b; \
+ sllx tmp, 7, tmp; \
+ wr tmp, 0, %asr27; \
+ clr tmp; \
+ .previous; \
+ brnz,pt tmp, 88b; \
+ sub tmp, 1, tmp; \
+ set BACKOFF_LIMIT, tmp; \
+ cmp reg, tmp; \
+ bg,pn %xcc, label; \
+ nop; \
+ ba,pt %xcc, label; \
+ sllx reg, 1, reg;
+
+#else
+
+#define BACKOFF_SETUP(reg)
+
+#define BACKOFF_LABEL(spin_label, continue_label) \
+ continue_label
+
+#define BACKOFF_SPIN(reg, tmp, label)
+
+#endif
+
+#endif /* _SPARC64_BACKOFF_H */
diff --git a/arch/sparc/include/asm/barrier.h b/arch/sparc/include/asm/barrier.h
new file mode 100644
index 000000000..c10b4164b
--- /dev/null
+++ b/arch/sparc/include/asm/barrier.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_BARRIER_H
+#define ___ASM_SPARC_BARRIER_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/barrier_64.h>
+#else
+#include <asm/barrier_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/barrier_32.h b/arch/sparc/include/asm/barrier_32.h
new file mode 100644
index 000000000..304f9c3f7
--- /dev/null
+++ b/arch/sparc/include/asm/barrier_32.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_BARRIER_H
+#define __SPARC_BARRIER_H
+
+#include <asm-generic/barrier.h>
+
+#endif /* !(__SPARC_BARRIER_H) */
diff --git a/arch/sparc/include/asm/barrier_64.h b/arch/sparc/include/asm/barrier_64.h
new file mode 100644
index 000000000..9fb148bd3
--- /dev/null
+++ b/arch/sparc/include/asm/barrier_64.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC64_BARRIER_H
+#define __SPARC64_BARRIER_H
+
+/* These are here in an effort to more fully work around Spitfire Errata
+ * #51. Essentially, if a memory barrier occurs soon after a mispredicted
+ * branch, the chip can stop executing instructions until a trap occurs.
+ * Therefore, if interrupts are disabled, the chip can hang forever.
+ *
+ * It used to be believed that the memory barrier had to be right in the
+ * delay slot, but a case has been traced recently wherein the memory barrier
+ * was one instruction after the branch delay slot and the chip still hung.
+ * The offending sequence was the following in sym_wakeup_done() of the
+ * sym53c8xx_2 driver:
+ *
+ * call sym_ccb_from_dsa, 0
+ * movge %icc, 0, %l0
+ * brz,pn %o0, .LL1303
+ * mov %o0, %l2
+ * membar #LoadLoad
+ *
+ * The branch has to be mispredicted for the bug to occur. Therefore, we put
+ * the memory barrier explicitly into a "branch always, predicted taken"
+ * delay slot to avoid the problem case.
+ */
+#define membar_safe(type) \
+do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
+ " membar " type "\n" \
+ "1:\n" \
+ : : : "memory"); \
+} while (0)
+
+/* The kernel always executes in TSO memory model these days,
+ * and furthermore most sparc64 chips implement more stringent
+ * memory ordering than required by the specifications.
+ */
+#define mb() membar_safe("#StoreLoad")
+#define rmb() __asm__ __volatile__("":::"memory")
+#define wmb() __asm__ __volatile__("":::"memory")
+
+#define __smp_store_release(p, v) \
+do { \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ WRITE_ONCE(*p, v); \
+} while (0)
+
+#define __smp_load_acquire(p) \
+({ \
+ typeof(*p) ___p1 = READ_ONCE(*p); \
+ compiletime_assert_atomic_type(*p); \
+ barrier(); \
+ ___p1; \
+})
+
+#define __smp_mb__before_atomic() barrier()
+#define __smp_mb__after_atomic() barrier()
+
+#include <asm-generic/barrier.h>
+
+#endif /* !(__SPARC64_BARRIER_H) */
diff --git a/arch/sparc/include/asm/bbc.h b/arch/sparc/include/asm/bbc.h
new file mode 100644
index 000000000..00a4f1161
--- /dev/null
+++ b/arch/sparc/include/asm/bbc.h
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * bbc.h: Defines for BootBus Controller found on UltraSPARC-III
+ * systems.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _SPARC64_BBC_H
+#define _SPARC64_BBC_H
+
+/* Register sizes are indicated by "B" (Byte, 1-byte),
+ * "H" (Half-word, 2 bytes), "W" (Word, 4 bytes) or
+ * "Q" (Quad, 8 bytes) inside brackets.
+ */
+
+#define BBC_AID 0x00 /* [B] Agent ID */
+#define BBC_DEVP 0x01 /* [B] Device Present */
+#define BBC_ARB 0x02 /* [B] Arbitration */
+#define BBC_QUIESCE 0x03 /* [B] Quiesce */
+#define BBC_WDACTION 0x04 /* [B] Watchdog Action */
+#define BBC_SPG 0x06 /* [B] Soft POR Gen */
+#define BBC_SXG 0x07 /* [B] Soft XIR Gen */
+#define BBC_PSRC 0x08 /* [W] POR Source */
+#define BBC_XSRC 0x0c /* [B] XIR Source */
+#define BBC_CSC 0x0d /* [B] Clock Synthesizers Control*/
+#define BBC_ES_CTRL 0x0e /* [H] Energy Star Control */
+#define BBC_ES_ACT 0x10 /* [W] E* Assert Change Time */
+#define BBC_ES_DACT 0x14 /* [B] E* De-Assert Change Time */
+#define BBC_ES_DABT 0x15 /* [B] E* De-Assert Bypass Time */
+#define BBC_ES_ABT 0x16 /* [H] E* Assert Bypass Time */
+#define BBC_ES_PST 0x18 /* [W] E* PLL Settle Time */
+#define BBC_ES_FSL 0x1c /* [W] E* Frequency Switch Latency*/
+#define BBC_EBUST 0x20 /* [Q] EBUS Timing */
+#define BBC_JTAG_CMD 0x28 /* [W] JTAG+ Command */
+#define BBC_JTAG_CTRL 0x2c /* [B] JTAG+ Control */
+#define BBC_I2C_SEL 0x2d /* [B] I2C Selection */
+#define BBC_I2C_0_S1 0x2e /* [B] I2C ctrlr-0 reg S1 */
+#define BBC_I2C_0_S0 0x2f /* [B] I2C ctrlr-0 regs S0,S0',S2,S3*/
+#define BBC_I2C_1_S1 0x30 /* [B] I2C ctrlr-1 reg S1 */
+#define BBC_I2C_1_S0 0x31 /* [B] I2C ctrlr-1 regs S0,S0',S2,S3*/
+#define BBC_KBD_BEEP 0x32 /* [B] Keyboard Beep */
+#define BBC_KBD_BCNT 0x34 /* [W] Keyboard Beep Counter */
+
+#define BBC_REGS_SIZE 0x40
+
+/* There is a 2K scratch ram area at offset 0x80000 but I doubt
+ * we will use it for anything.
+ */
+
+/* Agent ID register. This register shows the Safari Agent ID
+ * for the processors. The value returned depends upon which
+ * cpu is reading the register.
+ */
+#define BBC_AID_ID 0x07 /* Safari ID */
+#define BBC_AID_RESV 0xf8 /* Reserved */
+
+/* Device Present register. One can determine which cpus are actually
+ * present in the machine by interrogating this register.
+ */
+#define BBC_DEVP_CPU0 0x01 /* Processor 0 present */
+#define BBC_DEVP_CPU1 0x02 /* Processor 1 present */
+#define BBC_DEVP_CPU2 0x04 /* Processor 2 present */
+#define BBC_DEVP_CPU3 0x08 /* Processor 3 present */
+#define BBC_DEVP_RESV 0xf0 /* Reserved */
+
+/* Arbitration register. This register is used to block access to
+ * the BBC from a particular cpu.
+ */
+#define BBC_ARB_CPU0 0x01 /* Enable cpu 0 BBC arbitratrion */
+#define BBC_ARB_CPU1 0x02 /* Enable cpu 1 BBC arbitratrion */
+#define BBC_ARB_CPU2 0x04 /* Enable cpu 2 BBC arbitratrion */
+#define BBC_ARB_CPU3 0x08 /* Enable cpu 3 BBC arbitratrion */
+#define BBC_ARB_RESV 0xf0 /* Reserved */
+
+/* Quiesce register. Bus and BBC segments for cpus can be disabled
+ * with this register, ie. for hot plugging.
+ */
+#define BBC_QUIESCE_S02 0x01 /* Quiesce Safari segment for cpu 0 and 2 */
+#define BBC_QUIESCE_S13 0x02 /* Quiesce Safari segment for cpu 1 and 3 */
+#define BBC_QUIESCE_B02 0x04 /* Quiesce BBC segment for cpu 0 and 2 */
+#define BBC_QUIESCE_B13 0x08 /* Quiesce BBC segment for cpu 1 and 3 */
+#define BBC_QUIESCE_FD0 0x10 /* Disable Fatal_Error[0] reporting */
+#define BBC_QUIESCE_FD1 0x20 /* Disable Fatal_Error[1] reporting */
+#define BBC_QUIESCE_FD2 0x40 /* Disable Fatal_Error[2] reporting */
+#define BBC_QUIESCE_FD3 0x80 /* Disable Fatal_Error[3] reporting */
+
+/* Watchdog Action register. When the watchdog device timer expires
+ * a line is enabled to the BBC. The action BBC takes when this line
+ * is asserted can be controlled by this regiser.
+ */
+#define BBC_WDACTION_RST 0x01 /* When set, watchdog causes system reset.
+ * When clear, BBC ignores watchdog signal.
+ */
+#define BBC_WDACTION_RESV 0xfe /* Reserved */
+
+/* Soft_POR_GEN register. The POR (Power On Reset) signal may be asserted
+ * for specific processors or all processors via this register.
+ */
+#define BBC_SPG_CPU0 0x01 /* Assert POR for processor 0 */
+#define BBC_SPG_CPU1 0x02 /* Assert POR for processor 1 */
+#define BBC_SPG_CPU2 0x04 /* Assert POR for processor 2 */
+#define BBC_SPG_CPU3 0x08 /* Assert POR for processor 3 */
+#define BBC_SPG_CPUALL 0x10 /* Reset all processors and reset
+ * the entire system.
+ */
+#define BBC_SPG_RESV 0xe0 /* Reserved */
+
+/* Soft_XIR_GEN register. The XIR (eXternally Initiated Reset) signal
+ * may be asserted to specific processors via this register.
+ */
+#define BBC_SXG_CPU0 0x01 /* Assert XIR for processor 0 */
+#define BBC_SXG_CPU1 0x02 /* Assert XIR for processor 1 */
+#define BBC_SXG_CPU2 0x04 /* Assert XIR for processor 2 */
+#define BBC_SXG_CPU3 0x08 /* Assert XIR for processor 3 */
+#define BBC_SXG_RESV 0xf0 /* Reserved */
+
+/* POR Source register. One may identify the cause of the most recent
+ * reset by reading this register.
+ */
+#define BBC_PSRC_SPG0 0x0001 /* CPU 0 reset via BBC_SPG register */
+#define BBC_PSRC_SPG1 0x0002 /* CPU 1 reset via BBC_SPG register */
+#define BBC_PSRC_SPG2 0x0004 /* CPU 2 reset via BBC_SPG register */
+#define BBC_PSRC_SPG3 0x0008 /* CPU 3 reset via BBC_SPG register */
+#define BBC_PSRC_SPGSYS 0x0010 /* System reset via BBC_SPG register */
+#define BBC_PSRC_JTAG 0x0020 /* System reset via JTAG+ */
+#define BBC_PSRC_BUTTON 0x0040 /* System reset via push-button dongle */
+#define BBC_PSRC_PWRUP 0x0080 /* System reset via power-up */
+#define BBC_PSRC_FE0 0x0100 /* CPU 0 reported Fatal_Error */
+#define BBC_PSRC_FE1 0x0200 /* CPU 1 reported Fatal_Error */
+#define BBC_PSRC_FE2 0x0400 /* CPU 2 reported Fatal_Error */
+#define BBC_PSRC_FE3 0x0800 /* CPU 3 reported Fatal_Error */
+#define BBC_PSRC_FE4 0x1000 /* Schizo reported Fatal_Error */
+#define BBC_PSRC_FE5 0x2000 /* Safari device 5 reported Fatal_Error */
+#define BBC_PSRC_FE6 0x4000 /* CPMS reported Fatal_Error */
+#define BBC_PSRC_SYNTH 0x8000 /* System reset when on-board clock synthesizers
+ * were updated.
+ */
+#define BBC_PSRC_WDT 0x10000 /* System reset via Super I/O watchdog */
+#define BBC_PSRC_RSC 0x20000 /* System reset via RSC remote monitoring
+ * device
+ */
+
+/* XIR Source register. The source of an XIR event sent to a processor may
+ * be determined via this register.
+ */
+#define BBC_XSRC_SXG0 0x01 /* CPU 0 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG1 0x02 /* CPU 1 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG2 0x04 /* CPU 2 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_SXG3 0x08 /* CPU 3 received XIR via Soft_XIR_GEN reg */
+#define BBC_XSRC_JTAG 0x10 /* All CPUs received XIR via JTAG+ */
+#define BBC_XSRC_W_OR_B 0x20 /* All CPUs received XIR either because:
+ * a) Super I/O watchdog fired, or
+ * b) XIR push button was activated
+ */
+#define BBC_XSRC_RESV 0xc0 /* Reserved */
+
+/* Clock Synthesizers Control register. This register provides the big-bang
+ * programming interface to the two clock synthesizers of the machine.
+ */
+#define BBC_CSC_SLOAD 0x01 /* Directly connected to S_LOAD pins */
+#define BBC_CSC_SDATA 0x02 /* Directly connected to S_DATA pins */
+#define BBC_CSC_SCLOCK 0x04 /* Directly connected to S_CLOCK pins */
+#define BBC_CSC_RESV 0x78 /* Reserved */
+#define BBC_CSC_RST 0x80 /* Generate system reset when S_LOAD==1 */
+
+/* Energy Star Control register. This register is used to generate the
+ * clock frequency change trigger to the main system devices (Schizo and
+ * the processors). The transition occurs when bits in this register
+ * go from 0 to 1, only one bit must be set at once else no action
+ * occurs. Basically the sequence of events is:
+ * a) Choose new frequency: full, 1/2 or 1/32
+ * b) Program this desired frequency into the cpus and Schizo.
+ * c) Set the same value in this register.
+ * d) 16 system clocks later, clear this register.
+ */
+#define BBC_ES_CTRL_1_1 0x01 /* Full frequency */
+#define BBC_ES_CTRL_1_2 0x02 /* 1/2 frequency */
+#define BBC_ES_CTRL_1_32 0x20 /* 1/32 frequency */
+#define BBC_ES_RESV 0xdc /* Reserved */
+
+/* Energy Star Assert Change Time register. This determines the number
+ * of BBC clock cycles (which is half the system frequency) between
+ * the detection of FREEZE_ACK being asserted and the assertion of
+ * the CLK_CHANGE_L[2:0] signals.
+ */
+#define BBC_ES_ACT_VAL 0xff
+
+/* Energy Star Assert Bypass Time register. This determines the number
+ * of BBC clock cycles (which is half the system frequency) between
+ * the assertion of the CLK_CHANGE_L[2:0] signals and the assertion of
+ * the ESTAR_PLL_BYPASS signal.
+ */
+#define BBC_ES_ABT_VAL 0xffff
+
+/* Energy Star PLL Settle Time register. This determines the number of
+ * BBC clock cycles (which is half the system frequency) between the
+ * de-assertion of CLK_CHANGE_L[2:0] and the de-assertion of the FREEZE_L
+ * signal.
+ */
+#define BBC_ES_PST_VAL 0xffffffff
+
+/* Energy Star Frequency Switch Latency register. This is the number of
+ * BBC clocks between the de-assertion of CLK_CHANGE_L[2:0] and the first
+ * edge of the Safari clock at the new frequency.
+ */
+#define BBC_ES_FSL_VAL 0xffffffff
+
+/* Keyboard Beep control register. This is a simple enabler for the audio
+ * beep sound.
+ */
+#define BBC_KBD_BEEP_ENABLE 0x01 /* Enable beep */
+#define BBC_KBD_BEEP_RESV 0xfe /* Reserved */
+
+/* Keyboard Beep Counter register. There is a free-running counter inside
+ * the BBC which runs at half the system clock. The bit set in this register
+ * determines when the audio sound is generated. So for example if bit
+ * 10 is set, the audio beep will oscillate at 1/(2**12). The keyboard beep
+ * generator automatically selects a different bit to use if the system clock
+ * is changed via Energy Star.
+ */
+#define BBC_KBD_BCNT_BITS 0x0007fc00
+#define BBC_KBC_BCNT_RESV 0xfff803ff
+
+#endif /* _SPARC64_BBC_H */
+
diff --git a/arch/sparc/include/asm/bitext.h b/arch/sparc/include/asm/bitext.h
new file mode 100644
index 000000000..2c2a2d85e
--- /dev/null
+++ b/arch/sparc/include/asm/bitext.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * bitext.h: Bit string operations on the sparc, specific to architecture.
+ *
+ * Copyright 2002 Pete Zaitcev <zaitcev@yahoo.com>
+ */
+
+#ifndef _SPARC_BITEXT_H
+#define _SPARC_BITEXT_H
+
+#include <linux/spinlock.h>
+
+struct bit_map {
+ spinlock_t lock;
+ unsigned long *map;
+ int size;
+ int used;
+ int last_off;
+ int last_size;
+ int first_free;
+ int num_colors;
+};
+
+int bit_map_string_get(struct bit_map *t, int len, int align);
+void bit_map_clear(struct bit_map *t, int offset, int len);
+void bit_map_init(struct bit_map *t, unsigned long *map, int size);
+
+#endif /* defined(_SPARC_BITEXT_H) */
diff --git a/arch/sparc/include/asm/bitops.h b/arch/sparc/include/asm/bitops.h
new file mode 100644
index 000000000..4c431d274
--- /dev/null
+++ b/arch/sparc/include/asm/bitops.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_BITOPS_H
+#define ___ASM_SPARC_BITOPS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/bitops_64.h>
+#else
+#include <asm/bitops_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/bitops_32.h b/arch/sparc/include/asm/bitops_32.h
new file mode 100644
index 000000000..3448c191b
--- /dev/null
+++ b/arch/sparc/include/asm/bitops_32.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * bitops.h: Bit string operations on the Sparc.
+ *
+ * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 1996 Eddie C. Dost (ecd@skynet.be)
+ * Copyright 2001 Anton Blanchard (anton@samba.org)
+ */
+
+#ifndef _SPARC_BITOPS_H
+#define _SPARC_BITOPS_H
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+
+#ifdef __KERNEL__
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+unsigned long sp32___set_bit(unsigned long *addr, unsigned long mask);
+unsigned long sp32___clear_bit(unsigned long *addr, unsigned long mask);
+unsigned long sp32___change_bit(unsigned long *addr, unsigned long mask);
+
+/*
+ * Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
+ * is in the highest of the four bytes and bit '31' is the high bit
+ * within the first byte. Sparc is BIG-Endian. Unless noted otherwise
+ * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
+ */
+static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ return sp32___set_bit(ADDR, mask) != 0;
+}
+
+static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ (void) sp32___set_bit(ADDR, mask);
+}
+
+static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ return sp32___clear_bit(ADDR, mask) != 0;
+}
+
+static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ (void) sp32___clear_bit(ADDR, mask);
+}
+
+static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ return sp32___change_bit(ADDR, mask) != 0;
+}
+
+static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+ unsigned long *ADDR, mask;
+
+ ADDR = ((unsigned long *) addr) + (nr >> 5);
+ mask = 1 << (nr & 31);
+
+ (void) sp32___change_bit(ADDR, mask);
+}
+
+#include <asm-generic/bitops/non-atomic.h>
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* defined(_SPARC_BITOPS_H) */
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
new file mode 100644
index 000000000..005a8ae85
--- /dev/null
+++ b/arch/sparc/include/asm/bitops_64.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * bitops.h: Bit string operations on the V9.
+ *
+ * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC64_BITOPS_H
+#define _SPARC64_BITOPS_H
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <linux/compiler.h>
+#include <asm/byteorder.h>
+#include <asm/barrier.h>
+
+int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
+int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
+int test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
+void set_bit(unsigned long nr, volatile unsigned long *addr);
+void clear_bit(unsigned long nr, volatile unsigned long *addr);
+void change_bit(unsigned long nr, volatile unsigned long *addr);
+
+int fls(unsigned int word);
+int __fls(unsigned long word);
+
+#include <asm-generic/bitops/non-atomic.h>
+
+#include <asm-generic/bitops/fls64.h>
+
+#ifdef __KERNEL__
+
+int ffs(int x);
+unsigned long __ffs(unsigned long);
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/sched.h>
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+unsigned long __arch_hweight64(__u64 w);
+unsigned int __arch_hweight32(unsigned int w);
+unsigned int __arch_hweight16(unsigned int w);
+unsigned int __arch_hweight8(unsigned int w);
+
+#include <asm-generic/bitops/const_hweight.h>
+#include <asm-generic/bitops/lock.h>
+#endif /* __KERNEL__ */
+
+#ifdef __KERNEL__
+
+#include <asm-generic/bitops/le.h>
+
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* defined(_SPARC64_BITOPS_H) */
diff --git a/arch/sparc/include/asm/btext.h b/arch/sparc/include/asm/btext.h
new file mode 100644
index 000000000..01cdc4265
--- /dev/null
+++ b/arch/sparc/include/asm/btext.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_BTEXT_H
+#define _SPARC_BTEXT_H
+
+int btext_find_display(void);
+
+#endif /* _SPARC_BTEXT_H */
diff --git a/arch/sparc/include/asm/bug.h b/arch/sparc/include/asm/bug.h
new file mode 100644
index 000000000..ea53e418f
--- /dev/null
+++ b/arch/sparc/include/asm/bug.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_BUG_H
+#define _SPARC_BUG_H
+
+#ifdef CONFIG_BUG
+#include <linux/compiler.h>
+
+#ifdef CONFIG_DEBUG_BUGVERBOSE
+void do_BUG(const char *file, int line);
+#define BUG() do { \
+ do_BUG(__FILE__, __LINE__); \
+ barrier_before_unreachable(); \
+ __builtin_trap(); \
+} while (0)
+#else
+#define BUG() do { \
+ barrier_before_unreachable(); \
+ __builtin_trap(); \
+} while (0)
+#endif
+
+#define HAVE_ARCH_BUG
+#endif
+
+#include <asm-generic/bug.h>
+
+struct pt_regs;
+void __noreturn die_if_kernel(char *str, struct pt_regs *regs);
+
+#endif
diff --git a/arch/sparc/include/asm/cache.h b/arch/sparc/include/asm/cache.h
new file mode 100644
index 000000000..e62fd0e72
--- /dev/null
+++ b/arch/sparc/include/asm/cache.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* cache.h: Cache specific code for the Sparc. These include flushing
+ * and direct tag/data line access.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC_CACHE_H
+#define _SPARC_CACHE_H
+
+#define ARCH_SLAB_MINALIGN __alignof__(unsigned long long)
+
+#define L1_CACHE_SHIFT 5
+#define L1_CACHE_BYTES 32
+
+#ifdef CONFIG_SPARC32
+#define SMP_CACHE_BYTES_SHIFT 5
+#else
+#define SMP_CACHE_BYTES_SHIFT 6
+#endif
+
+#define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT)
+
+#define __read_mostly __section(".data..read_mostly")
+
+#endif /* !(_SPARC_CACHE_H) */
diff --git a/arch/sparc/include/asm/cacheflush.h b/arch/sparc/include/asm/cacheflush.h
new file mode 100644
index 000000000..881ac76ea
--- /dev/null
+++ b/arch/sparc/include/asm/cacheflush.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_CACHEFLUSH_H
+#define ___ASM_SPARC_CACHEFLUSH_H
+
+/* flush addr - to allow use of self-modifying code */
+#define flushi(addr) __asm__ __volatile__ ("flush %0" : : "r" (addr) : "memory")
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/cacheflush_64.h>
+#else
+#include <asm/cacheflush_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/cacheflush_32.h b/arch/sparc/include/asm/cacheflush_32.h
new file mode 100644
index 000000000..f3b7270bf
--- /dev/null
+++ b/arch/sparc/include/asm/cacheflush_32.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_CACHEFLUSH_H
+#define _SPARC_CACHEFLUSH_H
+
+#include <linux/page-flags.h>
+#include <asm/cachetlb_32.h>
+
+#define flush_cache_all() \
+ sparc32_cachetlb_ops->cache_all()
+#define flush_cache_mm(mm) \
+ sparc32_cachetlb_ops->cache_mm(mm)
+#define flush_cache_dup_mm(mm) \
+ sparc32_cachetlb_ops->cache_mm(mm)
+#define flush_cache_range(vma,start,end) \
+ sparc32_cachetlb_ops->cache_range(vma, start, end)
+#define flush_cache_page(vma,addr,pfn) \
+ sparc32_cachetlb_ops->cache_page(vma, addr)
+#define flush_icache_range(start, end) do { } while (0)
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
+ } while (0)
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page));\
+ memcpy(dst, src, len); \
+ } while (0)
+
+#define __flush_page_to_ram(addr) \
+ sparc32_cachetlb_ops->page_to_ram(addr)
+#define flush_sig_insns(mm,insn_addr) \
+ sparc32_cachetlb_ops->sig_insns(mm, insn_addr)
+#define flush_page_for_dma(addr) \
+ sparc32_cachetlb_ops->page_for_dma(addr)
+
+void sparc_flush_page_to_ram(struct page *page);
+void sparc_flush_folio_to_ram(struct folio *folio);
+
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+#define flush_dcache_folio(folio) sparc_flush_folio_to_ram(folio)
+static inline void flush_dcache_page(struct page *page)
+{
+ flush_dcache_folio(page_folio(page));
+}
+#define flush_dcache_mmap_lock(mapping) do { } while (0)
+#define flush_dcache_mmap_unlock(mapping) do { } while (0)
+
+#define flush_cache_vmap(start, end) flush_cache_all()
+#define flush_cache_vunmap(start, end) flush_cache_all()
+
+/* When a context switch happens we must flush all user windows so that
+ * the windows of the current process are flushed onto its stack. This
+ * way the windows are all clean for the next process and the stack
+ * frames are up to date.
+ */
+void flush_user_windows(void);
+void kill_user_windows(void);
+void flushw_all(void);
+
+#endif /* _SPARC_CACHEFLUSH_H */
diff --git a/arch/sparc/include/asm/cacheflush_64.h b/arch/sparc/include/asm/cacheflush_64.h
new file mode 100644
index 000000000..0e879004e
--- /dev/null
+++ b/arch/sparc/include/asm/cacheflush_64.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_CACHEFLUSH_H
+#define _SPARC64_CACHEFLUSH_H
+
+#include <asm/page.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/mm.h>
+
+/* Cache flush operations. */
+#define flushw_all() __asm__ __volatile__("flushw")
+
+void __flushw_user(void);
+#define flushw_user() __flushw_user()
+
+#define flush_user_windows flushw_user
+#define flush_register_windows flushw_all
+
+/* These are the same regardless of whether this is an SMP kernel or not. */
+#define flush_cache_mm(__mm) \
+ do { if ((__mm) == current->mm) flushw_user(); } while(0)
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+#define flush_cache_range(vma, start, end) \
+ flush_cache_mm((vma)->vm_mm)
+#define flush_cache_page(vma, page, pfn) \
+ flush_cache_mm((vma)->vm_mm)
+
+/*
+ * On spitfire, the icache doesn't snoop local stores and we don't
+ * use block commit stores (which invalidate icache lines) during
+ * module load, so we need this.
+ */
+void flush_icache_range(unsigned long start, unsigned long end);
+void __flush_icache_page(unsigned long);
+
+void __flush_dcache_page(void *addr, int flush_icache);
+void flush_dcache_folio_impl(struct folio *folio);
+#ifdef CONFIG_SMP
+void smp_flush_dcache_folio_impl(struct folio *folio, int cpu);
+void flush_dcache_folio_all(struct mm_struct *mm, struct folio *folio);
+#else
+#define smp_flush_dcache_folio_impl(folio, cpu) flush_dcache_folio_impl(folio)
+#define flush_dcache_folio_all(mm, folio) flush_dcache_folio_impl(folio)
+#endif
+
+void __flush_dcache_range(unsigned long start, unsigned long end);
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+void flush_dcache_folio(struct folio *folio);
+#define flush_dcache_folio flush_dcache_folio
+static inline void flush_dcache_page(struct page *page)
+{
+ flush_dcache_folio(page_folio(page));
+}
+
+void flush_ptrace_access(struct vm_area_struct *, struct page *,
+ unsigned long uaddr, void *kaddr,
+ unsigned long len, int write);
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page)); \
+ memcpy(dst, src, len); \
+ flush_ptrace_access(vma, page, vaddr, src, len, 0); \
+ } while (0)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+ do { \
+ flush_cache_page(vma, vaddr, page_to_pfn(page)); \
+ memcpy(dst, src, len); \
+ flush_ptrace_access(vma, page, vaddr, dst, len, 1); \
+ } while (0)
+
+#define flush_dcache_mmap_lock(mapping) do { } while (0)
+#define flush_dcache_mmap_unlock(mapping) do { } while (0)
+
+#define flush_cache_vmap(start, end) do { } while (0)
+#define flush_cache_vunmap(start, end) do { } while (0)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _SPARC64_CACHEFLUSH_H */
diff --git a/arch/sparc/include/asm/cachetlb_32.h b/arch/sparc/include/asm/cachetlb_32.h
new file mode 100644
index 000000000..534da70c6
--- /dev/null
+++ b/arch/sparc/include/asm/cachetlb_32.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_CACHETLB_H
+#define _SPARC_CACHETLB_H
+
+struct mm_struct;
+struct vm_area_struct;
+
+struct sparc32_cachetlb_ops {
+ void (*cache_all)(void);
+ void (*cache_mm)(struct mm_struct *);
+ void (*cache_range)(struct vm_area_struct *, unsigned long,
+ unsigned long);
+ void (*cache_page)(struct vm_area_struct *, unsigned long);
+
+ void (*tlb_all)(void);
+ void (*tlb_mm)(struct mm_struct *);
+ void (*tlb_range)(struct vm_area_struct *, unsigned long,
+ unsigned long);
+ void (*tlb_page)(struct vm_area_struct *, unsigned long);
+
+ void (*page_to_ram)(unsigned long);
+ void (*sig_insns)(struct mm_struct *, unsigned long);
+ void (*page_for_dma)(unsigned long);
+};
+extern const struct sparc32_cachetlb_ops *sparc32_cachetlb_ops;
+#ifdef CONFIG_SMP
+extern const struct sparc32_cachetlb_ops *local_ops;
+#endif
+
+#endif /* SPARC_CACHETLB_H */
diff --git a/arch/sparc/include/asm/chafsr.h b/arch/sparc/include/asm/chafsr.h
new file mode 100644
index 000000000..01540eca1
--- /dev/null
+++ b/arch/sparc/include/asm/chafsr.h
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_CHAFSR_H
+#define _SPARC64_CHAFSR_H
+
+/* Cheetah Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
+
+/* Comments indicate which processor variants on which the bit definition
+ * is valid. Codes are:
+ * ch --> cheetah
+ * ch+ --> cheetah plus
+ * jp --> jalapeno
+ */
+
+/* All bits of this register except M_SYNDROME and E_SYNDROME are
+ * read, write 1 to clear. M_SYNDROME and E_SYNDROME are read-only.
+ */
+
+/* Software bit set by linux trap handlers to indicate that the trap was
+ * signalled at %tl >= 1.
+ */
+#define CHAFSR_TL1 (1UL << 63UL) /* n/a */
+
+/* Unmapped error from system bus for prefetch queue or
+ * store queue read operation
+ */
+#define CHPAFSR_DTO (1UL << 59UL) /* ch+ */
+
+/* Bus error from system bus for prefetch queue or store queue
+ * read operation
+ */
+#define CHPAFSR_DBERR (1UL << 58UL) /* ch+ */
+
+/* Hardware corrected E-cache Tag ECC error */
+#define CHPAFSR_THCE (1UL << 57UL) /* ch+ */
+/* System interface protocol error, hw timeout caused */
+#define JPAFSR_JETO (1UL << 57UL) /* jp */
+
+/* SW handled correctable E-cache Tag ECC error */
+#define CHPAFSR_TSCE (1UL << 56UL) /* ch+ */
+/* Parity error on system snoop results */
+#define JPAFSR_SCE (1UL << 56UL) /* jp */
+
+/* Uncorrectable E-cache Tag ECC error */
+#define CHPAFSR_TUE (1UL << 55UL) /* ch+ */
+/* System interface protocol error, illegal command detected */
+#define JPAFSR_JEIC (1UL << 55UL) /* jp */
+
+/* Uncorrectable system bus data ECC error due to prefetch
+ * or store fill request
+ */
+#define CHPAFSR_DUE (1UL << 54UL) /* ch+ */
+/* System interface protocol error, illegal ADTYPE detected */
+#define JPAFSR_JEIT (1UL << 54UL) /* jp */
+
+/* Multiple errors of the same type have occurred. This bit is set when
+ * an uncorrectable error or a SW correctable error occurs and the status
+ * bit to report that error is already set. When multiple errors of
+ * different types are indicated by setting multiple status bits.
+ *
+ * This bit is not set if multiple HW corrected errors with the same
+ * status bit occur, only uncorrectable and SW correctable ones have
+ * this behavior.
+ *
+ * This bit is not set when multiple ECC errors happen within a single
+ * 64-byte system bus transaction. Only the first ECC error in a 16-byte
+ * subunit will be logged. All errors in subsequent 16-byte subunits
+ * from the same 64-byte transaction are ignored.
+ */
+#define CHAFSR_ME (1UL << 53UL) /* ch,ch+,jp */
+
+/* Privileged state error has occurred. This is a capture of PSTATE.PRIV
+ * at the time the error is detected.
+ */
+#define CHAFSR_PRIV (1UL << 52UL) /* ch,ch+,jp */
+
+/* The following bits 51 (CHAFSR_PERR) to 33 (CHAFSR_CE) are sticky error
+ * bits and record the most recently detected errors. Bits accumulate
+ * errors that have been detected since the last write to clear the bit.
+ */
+
+/* System interface protocol error. The processor asserts its' ERROR
+ * pin when this event occurs and it also logs a specific cause code
+ * into a JTAG scannable flop.
+ */
+#define CHAFSR_PERR (1UL << 51UL) /* ch,ch+,jp */
+
+/* Internal processor error. The processor asserts its' ERROR
+ * pin when this event occurs and it also logs a specific cause code
+ * into a JTAG scannable flop.
+ */
+#define CHAFSR_IERR (1UL << 50UL) /* ch,ch+,jp */
+
+/* System request parity error on incoming address */
+#define CHAFSR_ISAP (1UL << 49UL) /* ch,ch+,jp */
+
+/* HW Corrected system bus MTAG ECC error */
+#define CHAFSR_EMC (1UL << 48UL) /* ch,ch+ */
+/* Parity error on L2 cache tag SRAM */
+#define JPAFSR_ETP (1UL << 48UL) /* jp */
+
+/* Uncorrectable system bus MTAG ECC error */
+#define CHAFSR_EMU (1UL << 47UL) /* ch,ch+ */
+/* Out of range memory error has occurred */
+#define JPAFSR_OM (1UL << 47UL) /* jp */
+
+/* HW Corrected system bus data ECC error for read of interrupt vector */
+#define CHAFSR_IVC (1UL << 46UL) /* ch,ch+ */
+/* Error due to unsupported store */
+#define JPAFSR_UMS (1UL << 46UL) /* jp */
+
+/* Uncorrectable system bus data ECC error for read of interrupt vector */
+#define CHAFSR_IVU (1UL << 45UL) /* ch,ch+,jp */
+
+/* Unmapped error from system bus */
+#define CHAFSR_TO (1UL << 44UL) /* ch,ch+,jp */
+
+/* Bus error response from system bus */
+#define CHAFSR_BERR (1UL << 43UL) /* ch,ch+,jp */
+
+/* SW Correctable E-cache ECC error for instruction fetch or data access
+ * other than block load.
+ */
+#define CHAFSR_UCC (1UL << 42UL) /* ch,ch+,jp */
+
+/* Uncorrectable E-cache ECC error for instruction fetch or data access
+ * other than block load.
+ */
+#define CHAFSR_UCU (1UL << 41UL) /* ch,ch+,jp */
+
+/* Copyout HW Corrected ECC error */
+#define CHAFSR_CPC (1UL << 40UL) /* ch,ch+,jp */
+
+/* Copyout Uncorrectable ECC error */
+#define CHAFSR_CPU (1UL << 39UL) /* ch,ch+,jp */
+
+/* HW Corrected ECC error from E-cache for writeback */
+#define CHAFSR_WDC (1UL << 38UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from E-cache for writeback */
+#define CHAFSR_WDU (1UL << 37UL) /* ch,ch+,jp */
+
+/* HW Corrected ECC error from E-cache for store merge or block load */
+#define CHAFSR_EDC (1UL << 36UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from E-cache for store merge or block load */
+#define CHAFSR_EDU (1UL << 35UL) /* ch,ch+,jp */
+
+/* Uncorrectable system bus data ECC error for read of memory or I/O */
+#define CHAFSR_UE (1UL << 34UL) /* ch,ch+,jp */
+
+/* HW Corrected system bus data ECC error for read of memory or I/O */
+#define CHAFSR_CE (1UL << 33UL) /* ch,ch+,jp */
+
+/* Uncorrectable ECC error from remote cache/memory */
+#define JPAFSR_RUE (1UL << 32UL) /* jp */
+
+/* Correctable ECC error from remote cache/memory */
+#define JPAFSR_RCE (1UL << 31UL) /* jp */
+
+/* JBUS parity error on returned read data */
+#define JPAFSR_BP (1UL << 30UL) /* jp */
+
+/* JBUS parity error on data for writeback or block store */
+#define JPAFSR_WBP (1UL << 29UL) /* jp */
+
+/* Foreign read to DRAM incurring correctable ECC error */
+#define JPAFSR_FRC (1UL << 28UL) /* jp */
+
+/* Foreign read to DRAM incurring uncorrectable ECC error */
+#define JPAFSR_FRU (1UL << 27UL) /* jp */
+
+#define CHAFSR_ERRORS (CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP | CHAFSR_EMC | \
+ CHAFSR_EMU | CHAFSR_IVC | CHAFSR_IVU | CHAFSR_TO | \
+ CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | CHAFSR_CPC | \
+ CHAFSR_CPU | CHAFSR_WDC | CHAFSR_WDU | CHAFSR_EDC | \
+ CHAFSR_EDU | CHAFSR_UE | CHAFSR_CE)
+#define CHPAFSR_ERRORS (CHPAFSR_DTO | CHPAFSR_DBERR | CHPAFSR_THCE | \
+ CHPAFSR_TSCE | CHPAFSR_TUE | CHPAFSR_DUE | \
+ CHAFSR_PERR | CHAFSR_IERR | CHAFSR_ISAP | CHAFSR_EMC | \
+ CHAFSR_EMU | CHAFSR_IVC | CHAFSR_IVU | CHAFSR_TO | \
+ CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | CHAFSR_CPC | \
+ CHAFSR_CPU | CHAFSR_WDC | CHAFSR_WDU | CHAFSR_EDC | \
+ CHAFSR_EDU | CHAFSR_UE | CHAFSR_CE)
+#define JPAFSR_ERRORS (JPAFSR_JETO | JPAFSR_SCE | JPAFSR_JEIC | \
+ JPAFSR_JEIT | CHAFSR_PERR | CHAFSR_IERR | \
+ CHAFSR_ISAP | JPAFSR_ETP | JPAFSR_OM | \
+ JPAFSR_UMS | CHAFSR_IVU | CHAFSR_TO | \
+ CHAFSR_BERR | CHAFSR_UCC | CHAFSR_UCU | \
+ CHAFSR_CPC | CHAFSR_CPU | CHAFSR_WDC | \
+ CHAFSR_WDU | CHAFSR_EDC | CHAFSR_EDU | \
+ CHAFSR_UE | CHAFSR_CE | JPAFSR_RUE | \
+ JPAFSR_RCE | JPAFSR_BP | JPAFSR_WBP | \
+ JPAFSR_FRC | JPAFSR_FRU)
+
+/* Active JBUS request signal when error occurred */
+#define JPAFSR_JBREQ (0x7UL << 24UL) /* jp */
+#define JPAFSR_JBREQ_SHIFT 24UL
+
+/* L2 cache way information */
+#define JPAFSR_ETW (0x3UL << 22UL) /* jp */
+#define JPAFSR_ETW_SHIFT 22UL
+
+/* System bus MTAG ECC syndrome. This field captures the status of the
+ * first occurrence of the highest-priority error according to the M_SYND
+ * overwrite policy. After the AFSR sticky bit, corresponding to the error
+ * for which the M_SYND is reported, is cleared, the contents of the M_SYND
+ * field will be unchanged by will be unfrozen for further error capture.
+ */
+#define CHAFSR_M_SYNDROME (0xfUL << 16UL) /* ch,ch+,jp */
+#define CHAFSR_M_SYNDROME_SHIFT 16UL
+
+/* Agenid Id of the foreign device causing the UE/CE errors */
+#define JPAFSR_AID (0x1fUL << 9UL) /* jp */
+#define JPAFSR_AID_SHIFT 9UL
+
+/* System bus or E-cache data ECC syndrome. This field captures the status
+ * of the first occurrence of the highest-priority error according to the
+ * E_SYND overwrite policy. After the AFSR sticky bit, corresponding to the
+ * error for which the E_SYND is reported, is cleare, the contents of the E_SYND
+ * field will be unchanged but will be unfrozen for further error capture.
+ */
+#define CHAFSR_E_SYNDROME (0x1ffUL << 0UL) /* ch,ch+,jp */
+#define CHAFSR_E_SYNDROME_SHIFT 0UL
+
+/* The AFSR must be explicitly cleared by software, it is not cleared automatically
+ * by a read. Writes to bits <51:33> with bits set will clear the corresponding
+ * bits in the AFSR. Bits associated with disrupting traps must be cleared before
+ * interrupts are re-enabled to prevent multiple traps for the same error. I.e.
+ * PSTATE.IE and AFSR bits control delivery of disrupting traps.
+ *
+ * Since there is only one AFAR, when multiple events have been logged by the
+ * bits in the AFSR, at most one of these events will have its status captured
+ * in the AFAR. The highest priority of those event bits will get AFAR logging.
+ * The AFAR will be unlocked and available to capture the address of another event
+ * as soon as the one bit in AFSR that corresponds to the event logged in AFAR is
+ * cleared. For example, if AFSR.CE is detected, then AFSR.UE (which overwrites
+ * the AFAR), and AFSR.UE is cleared by not AFSR.CE, then the AFAR will be unlocked
+ * and ready for another event, even though AFSR.CE is still set. The same rules
+ * also apply to the M_SYNDROME and E_SYNDROME fields of the AFSR.
+ */
+
+#endif /* _SPARC64_CHAFSR_H */
diff --git a/arch/sparc/include/asm/checksum.h b/arch/sparc/include/asm/checksum.h
new file mode 100644
index 000000000..f2ac13323
--- /dev/null
+++ b/arch/sparc/include/asm/checksum.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_CHECKSUM_H
+#define ___ASM_SPARC_CHECKSUM_H
+#define _HAVE_ARCH_CSUM_AND_COPY
+#define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
+#define HAVE_CSUM_COPY_USER
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/checksum_64.h>
+#else
+#include <asm/checksum_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/checksum_32.h b/arch/sparc/include/asm/checksum_32.h
new file mode 100644
index 000000000..ce11e0ad8
--- /dev/null
+++ b/arch/sparc/include/asm/checksum_32.h
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_CHECKSUM_H
+#define __SPARC_CHECKSUM_H
+
+/* checksum.h: IP/UDP/TCP checksum routines on the Sparc.
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1996 Eddie C. Dost
+ * Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ * Alpha checksum c-code
+ * ix86 inline assembly
+ * RFC1071 Computing the Internet Checksum
+ */
+
+#include <linux/in6.h>
+#include <linux/uaccess.h>
+
+/* computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void *buff, int len, __wsum sum);
+
+/* the same as csum_partial, but copies from fs:src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+unsigned int __csum_partial_copy_sparc_generic (const unsigned char *, unsigned char *);
+
+static inline __wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len)
+{
+ register unsigned int ret asm("o0") = (unsigned int)src;
+ register char *d asm("o1") = dst;
+ register int l asm("g1") = len;
+
+ __asm__ __volatile__ (
+ "call __csum_partial_copy_sparc_generic\n\t"
+ " mov -1, %%g7\n"
+ : "=&r" (ret), "=&r" (d), "=&r" (l)
+ : "0" (ret), "1" (d), "2" (l)
+ : "o2", "o3", "o4", "o5", "o7",
+ "g2", "g3", "g4", "g5", "g7",
+ "memory", "cc");
+ return (__force __wsum)ret;
+}
+
+static inline __wsum
+csum_and_copy_from_user(const void __user *src, void *dst, int len)
+{
+ if (unlikely(!access_ok(src, len)))
+ return 0;
+ return csum_partial_copy_nocheck((__force void *)src, dst, len);
+}
+
+static inline __wsum
+csum_and_copy_to_user(const void *src, void __user *dst, int len)
+{
+ if (!access_ok(dst, len))
+ return 0;
+ return csum_partial_copy_nocheck(src, (__force void *)dst, len);
+}
+
+/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
+ * the majority of the time.
+ */
+static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+{
+ __sum16 sum;
+
+ /* Note: We must read %2 before we touch %0 for the first time,
+ * because GCC can legitimately use the same register for
+ * both operands.
+ */
+ __asm__ __volatile__("sub\t%2, 4, %%g4\n\t"
+ "ld\t[%1 + 0x00], %0\n\t"
+ "ld\t[%1 + 0x04], %%g2\n\t"
+ "ld\t[%1 + 0x08], %%g3\n\t"
+ "addcc\t%%g2, %0, %0\n\t"
+ "addxcc\t%%g3, %0, %0\n\t"
+ "ld\t[%1 + 0x0c], %%g2\n\t"
+ "ld\t[%1 + 0x10], %%g3\n\t"
+ "addxcc\t%%g2, %0, %0\n\t"
+ "addx\t%0, %%g0, %0\n"
+ "1:\taddcc\t%%g3, %0, %0\n\t"
+ "add\t%1, 4, %1\n\t"
+ "addxcc\t%0, %%g0, %0\n\t"
+ "subcc\t%%g4, 1, %%g4\n\t"
+ "be,a\t2f\n\t"
+ "sll\t%0, 16, %%g2\n\t"
+ "b\t1b\n\t"
+ "ld\t[%1 + 0x10], %%g3\n"
+ "2:\taddcc\t%0, %%g2, %%g2\n\t"
+ "srl\t%%g2, 16, %0\n\t"
+ "addx\t%0, %%g0, %0\n\t"
+ "xnor\t%%g0, %0, %0"
+ : "=r" (sum), "=&r" (iph)
+ : "r" (ihl), "1" (iph)
+ : "g2", "g3", "g4", "cc", "memory");
+ return sum;
+}
+
+/* Fold a partial checksum without adding pseudo headers. */
+static inline __sum16 csum_fold(__wsum sum)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__("addcc\t%0, %1, %1\n\t"
+ "srl\t%1, 16, %1\n\t"
+ "addx\t%1, %%g0, %1\n\t"
+ "xnor\t%%g0, %1, %0"
+ : "=&r" (sum), "=r" (tmp)
+ : "0" (sum), "1" ((__force u32)sum<<16)
+ : "cc");
+ return (__force __sum16)sum;
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ __u32 len, __u8 proto,
+ __wsum sum)
+{
+ __asm__ __volatile__("addcc\t%1, %0, %0\n\t"
+ "addxcc\t%2, %0, %0\n\t"
+ "addxcc\t%3, %0, %0\n\t"
+ "addx\t%0, %%g0, %0\n\t"
+ : "=r" (sum), "=r" (saddr)
+ : "r" (daddr), "r" (proto + len), "0" (sum),
+ "1" (saddr)
+ : "cc");
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ __u32 len, __u8 proto,
+ __wsum sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, __u8 proto, __wsum sum)
+{
+ __asm__ __volatile__ (
+ "addcc %3, %4, %%g4\n\t"
+ "addxcc %5, %%g4, %%g4\n\t"
+ "ld [%2 + 0x0c], %%g2\n\t"
+ "ld [%2 + 0x08], %%g3\n\t"
+ "addxcc %%g2, %%g4, %%g4\n\t"
+ "ld [%2 + 0x04], %%g2\n\t"
+ "addxcc %%g3, %%g4, %%g4\n\t"
+ "ld [%2 + 0x00], %%g3\n\t"
+ "addxcc %%g2, %%g4, %%g4\n\t"
+ "ld [%1 + 0x0c], %%g2\n\t"
+ "addxcc %%g3, %%g4, %%g4\n\t"
+ "ld [%1 + 0x08], %%g3\n\t"
+ "addxcc %%g2, %%g4, %%g4\n\t"
+ "ld [%1 + 0x04], %%g2\n\t"
+ "addxcc %%g3, %%g4, %%g4\n\t"
+ "ld [%1 + 0x00], %%g3\n\t"
+ "addxcc %%g2, %%g4, %%g4\n\t"
+ "addxcc %%g3, %%g4, %0\n\t"
+ "addx 0, %0, %0\n"
+ : "=&r" (sum)
+ : "r" (saddr), "r" (daddr),
+ "r"(htonl(len)), "r"(htonl(proto)), "r"(sum)
+ : "g2", "g3", "g4", "cc");
+
+ return csum_fold(sum);
+}
+
+/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+#define HAVE_ARCH_CSUM_ADD
+static inline __wsum csum_add(__wsum csum, __wsum addend)
+{
+ __asm__ __volatile__(
+ "addcc %0, %1, %0\n"
+ "addx %0, %%g0, %0"
+ : "=r" (csum)
+ : "r" (addend), "0" (csum));
+
+ return csum;
+}
+
+#endif /* !(__SPARC_CHECKSUM_H) */
diff --git a/arch/sparc/include/asm/checksum_64.h b/arch/sparc/include/asm/checksum_64.h
new file mode 100644
index 000000000..d6b59461e
--- /dev/null
+++ b/arch/sparc/include/asm/checksum_64.h
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC64_CHECKSUM_H
+#define __SPARC64_CHECKSUM_H
+
+/* checksum.h: IP/UDP/TCP checksum routines on the V9.
+ *
+ * Copyright(C) 1995 Linus Torvalds
+ * Copyright(C) 1995 Miguel de Icaza
+ * Copyright(C) 1996 David S. Miller
+ * Copyright(C) 1996 Eddie C. Dost
+ * Copyright(C) 1997 Jakub Jelinek
+ *
+ * derived from:
+ * Alpha checksum c-code
+ * ix86 inline assembly
+ * RFC1071 Computing the Internet Checksum
+ */
+
+#include <linux/in6.h>
+#include <linux/uaccess.h>
+
+/* computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+__wsum csum_partial(const void * buff, int len, __wsum sum);
+
+/* the same as csum_partial, but copies from user space while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len);
+__wsum csum_and_copy_from_user(const void __user *src, void *dst, int len);
+__wsum csum_and_copy_to_user(const void *src, void __user *dst, int len);
+
+/* ihl is always 5 or greater, almost always is 5, and iph is word aligned
+ * the majority of the time.
+ */
+__sum16 ip_fast_csum(const void *iph, unsigned int ihl);
+
+/* Fold a partial checksum without adding pseudo headers. */
+static inline __sum16 csum_fold(__wsum sum)
+{
+ unsigned int tmp;
+
+ __asm__ __volatile__(
+" addcc %0, %1, %1\n"
+" srl %1, 16, %1\n"
+" addc %1, %%g0, %1\n"
+" xnor %%g0, %1, %0\n"
+ : "=&r" (sum), "=r" (tmp)
+ : "0" (sum), "1" ((__force u32)sum<<16)
+ : "cc");
+ return (__force __sum16)sum;
+}
+
+static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
+ __u32 len, __u8 proto,
+ __wsum sum)
+{
+ __asm__ __volatile__(
+" addcc %1, %0, %0\n"
+" addccc %2, %0, %0\n"
+" addccc %3, %0, %0\n"
+" addc %0, %%g0, %0\n"
+ : "=r" (sum), "=r" (saddr)
+ : "r" (daddr), "r" (proto + len), "0" (sum), "1" (saddr)
+ : "cc");
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr,
+ __u32 len, __u8 proto,
+ __wsum sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+
+static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __u32 len, __u8 proto, __wsum sum)
+{
+ __asm__ __volatile__ (
+" addcc %3, %4, %%g7\n"
+" addccc %5, %%g7, %%g7\n"
+" lduw [%2 + 0x0c], %%g2\n"
+" lduw [%2 + 0x08], %%g3\n"
+" addccc %%g2, %%g7, %%g7\n"
+" lduw [%2 + 0x04], %%g2\n"
+" addccc %%g3, %%g7, %%g7\n"
+" lduw [%2 + 0x00], %%g3\n"
+" addccc %%g2, %%g7, %%g7\n"
+" lduw [%1 + 0x0c], %%g2\n"
+" addccc %%g3, %%g7, %%g7\n"
+" lduw [%1 + 0x08], %%g3\n"
+" addccc %%g2, %%g7, %%g7\n"
+" lduw [%1 + 0x04], %%g2\n"
+" addccc %%g3, %%g7, %%g7\n"
+" lduw [%1 + 0x00], %%g3\n"
+" addccc %%g2, %%g7, %%g7\n"
+" addccc %%g3, %%g7, %0\n"
+" addc 0, %0, %0\n"
+ : "=&r" (sum)
+ : "r" (saddr), "r" (daddr), "r"(htonl(len)),
+ "r"(htonl(proto)), "r"(sum)
+ : "g2", "g3", "g7", "cc");
+
+ return csum_fold(sum);
+}
+
+/* this routine is used for miscellaneous IP-like checksums, mainly in icmp.c */
+static inline __sum16 ip_compute_csum(const void *buff, int len)
+{
+ return csum_fold(csum_partial(buff, len, 0));
+}
+
+#define HAVE_ARCH_CSUM_ADD
+static inline __wsum csum_add(__wsum csum, __wsum addend)
+{
+ __asm__ __volatile__(
+ "addcc %0, %1, %0\n"
+ "addx %0, %%g0, %0"
+ : "=r" (csum)
+ : "r" (addend), "0" (csum));
+
+ return csum;
+}
+
+#endif /* !(__SPARC64_CHECKSUM_H) */
diff --git a/arch/sparc/include/asm/chmctrl.h b/arch/sparc/include/asm/chmctrl.h
new file mode 100644
index 000000000..96f043cb2
--- /dev/null
+++ b/arch/sparc/include/asm/chmctrl.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_CHMCTRL_H
+#define _SPARC64_CHMCTRL_H
+
+/* Cheetah memory controller programmable registers. */
+#define CHMCTRL_TCTRL1 0x00 /* Memory Timing Control I */
+#define CHMCTRL_TCTRL2 0x08 /* Memory Timing Control II */
+#define CHMCTRL_TCTRL3 0x38 /* Memory Timing Control III */
+#define CHMCTRL_TCTRL4 0x40 /* Memory Timing Control IV */
+#define CHMCTRL_DECODE1 0x10 /* Memory Address Decode I */
+#define CHMCTRL_DECODE2 0x18 /* Memory Address Decode II */
+#define CHMCTRL_DECODE3 0x20 /* Memory Address Decode III */
+#define CHMCTRL_DECODE4 0x28 /* Memory Address Decode IV */
+#define CHMCTRL_MACTRL 0x30 /* Memory Address Control */
+
+/* Memory Timing Control I */
+#define TCTRL1_SDRAMCTL_DLY 0xf000000000000000UL
+#define TCTRL1_SDRAMCTL_DLY_SHIFT 60
+#define TCTRL1_SDRAMCLK_DLY 0x0e00000000000000UL
+#define TCTRL1_SDRAMCLK_DLY_SHIFT 57
+#define TCTRL1_R 0x0100000000000000UL
+#define TCTRL1_R_SHIFT 56
+#define TCTRL1_AUTORFR_CYCLE 0x00fe000000000000UL
+#define TCTRL1_AUTORFR_CYCLE_SHIFT 49
+#define TCTRL1_RD_WAIT 0x0001f00000000000UL
+#define TCTRL1_RD_WAIT_SHIFT 44
+#define TCTRL1_PC_CYCLE 0x00000fc000000000UL
+#define TCTRL1_PC_CYCLE_SHIFT 38
+#define TCTRL1_WR_MORE_RAS_PW 0x0000003f00000000UL
+#define TCTRL1_WR_MORE_RAS_PW_SHIFT 32
+#define TCTRL1_RD_MORE_RAW_PW 0x00000000fc000000UL
+#define TCTRL1_RD_MORE_RAS_PW_SHIFT 26
+#define TCTRL1_ACT_WR_DLY 0x0000000003f00000UL
+#define TCTRL1_ACT_WR_DLY_SHIFT 20
+#define TCTRL1_ACT_RD_DLY 0x00000000000fc000UL
+#define TCTRL1_ACT_RD_DLY_SHIFT 14
+#define TCTRL1_BANK_PRESENT 0x0000000000003000UL
+#define TCTRL1_BANK_PRESENT_SHIFT 12
+#define TCTRL1_RFR_INT 0x0000000000000ff8UL
+#define TCTRL1_RFR_INT_SHIFT 3
+#define TCTRL1_SET_MODE_REG 0x0000000000000004UL
+#define TCTRL1_SET_MODE_REG_SHIFT 2
+#define TCTRL1_RFR_ENABLE 0x0000000000000002UL
+#define TCTRL1_RFR_ENABLE_SHIFT 1
+#define TCTRL1_PRECHG_ALL 0x0000000000000001UL
+#define TCTRL1_PRECHG_ALL_SHIFT 0
+
+/* Memory Timing Control II */
+#define TCTRL2_WR_MSEL_DLY 0xfc00000000000000UL
+#define TCTRL2_WR_MSEL_DLY_SHIFT 58
+#define TCTRL2_RD_MSEL_DLY 0x03f0000000000000UL
+#define TCTRL2_RD_MSEL_DLY_SHIFT 52
+#define TCTRL2_WRDATA_THLD 0x000c000000000000UL
+#define TCTRL2_WRDATA_THLD_SHIFT 50
+#define TCTRL2_RDWR_RD_TI_DLY 0x0003f00000000000UL
+#define TCTRL2_RDWR_RD_TI_DLY_SHIFT 44
+#define TCTRL2_AUTOPRECHG_ENBL 0x0000080000000000UL
+#define TCTRL2_AUTOPRECHG_ENBL_SHIFT 43
+#define TCTRL2_RDWR_PI_MORE_DLY 0x000007c000000000UL
+#define TCTRL2_RDWR_PI_MORE_DLY_SHIFT 38
+#define TCTRL2_RDWR_1_DLY 0x0000003f00000000UL
+#define TCTRL2_RDWR_1_DLY_SHIFT 32
+#define TCTRL2_WRWR_PI_MORE_DLY 0x00000000f8000000UL
+#define TCTRL2_WRWR_PI_MORE_DLY_SHIFT 27
+#define TCTRL2_WRWR_1_DLY 0x0000000007e00000UL
+#define TCTRL2_WRWR_1_DLY_SHIFT 21
+#define TCTRL2_RDWR_RD_PI_MORE_DLY 0x00000000001f0000UL
+#define TCTRL2_RDWR_RD_PI_MORE_DLY_SHIFT 16
+#define TCTRL2_R 0x0000000000008000UL
+#define TCTRL2_R_SHIFT 15
+#define TCTRL2_SDRAM_MODE_REG_DATA 0x0000000000007fffUL
+#define TCTRL2_SDRAM_MODE_REG_DATA_SHIFT 0
+
+/* Memory Timing Control III */
+#define TCTRL3_SDRAM_CTL_DLY 0xf000000000000000UL
+#define TCTRL3_SDRAM_CTL_DLY_SHIFT 60
+#define TCTRL3_SDRAM_CLK_DLY 0x0e00000000000000UL
+#define TCTRL3_SDRAM_CLK_DLY_SHIFT 57
+#define TCTRL3_R 0x0100000000000000UL
+#define TCTRL3_R_SHIFT 56
+#define TCTRL3_AUTO_RFR_CYCLE 0x00fe000000000000UL
+#define TCTRL3_AUTO_RFR_CYCLE_SHIFT 49
+#define TCTRL3_RD_WAIT 0x0001f00000000000UL
+#define TCTRL3_RD_WAIT_SHIFT 44
+#define TCTRL3_PC_CYCLE 0x00000fc000000000UL
+#define TCTRL3_PC_CYCLE_SHIFT 38
+#define TCTRL3_WR_MORE_RAW_PW 0x0000003f00000000UL
+#define TCTRL3_WR_MORE_RAW_PW_SHIFT 32
+#define TCTRL3_RD_MORE_RAW_PW 0x00000000fc000000UL
+#define TCTRL3_RD_MORE_RAW_PW_SHIFT 26
+#define TCTRL3_ACT_WR_DLY 0x0000000003f00000UL
+#define TCTRL3_ACT_WR_DLY_SHIFT 20
+#define TCTRL3_ACT_RD_DLY 0x00000000000fc000UL
+#define TCTRL3_ACT_RD_DLY_SHIFT 14
+#define TCTRL3_BANK_PRESENT 0x0000000000003000UL
+#define TCTRL3_BANK_PRESENT_SHIFT 12
+#define TCTRL3_RFR_INT 0x0000000000000ff8UL
+#define TCTRL3_RFR_INT_SHIFT 3
+#define TCTRL3_SET_MODE_REG 0x0000000000000004UL
+#define TCTRL3_SET_MODE_REG_SHIFT 2
+#define TCTRL3_RFR_ENABLE 0x0000000000000002UL
+#define TCTRL3_RFR_ENABLE_SHIFT 1
+#define TCTRL3_PRECHG_ALL 0x0000000000000001UL
+#define TCTRL3_PRECHG_ALL_SHIFT 0
+
+/* Memory Timing Control IV */
+#define TCTRL4_WR_MSEL_DLY 0xfc00000000000000UL
+#define TCTRL4_WR_MSEL_DLY_SHIFT 58
+#define TCTRL4_RD_MSEL_DLY 0x03f0000000000000UL
+#define TCTRL4_RD_MSEL_DLY_SHIFT 52
+#define TCTRL4_WRDATA_THLD 0x000c000000000000UL
+#define TCTRL4_WRDATA_THLD_SHIFT 50
+#define TCTRL4_RDWR_RD_RI_DLY 0x0003f00000000000UL
+#define TCTRL4_RDWR_RD_RI_DLY_SHIFT 44
+#define TCTRL4_AUTO_PRECHG_ENBL 0x0000080000000000UL
+#define TCTRL4_AUTO_PRECHG_ENBL_SHIFT 43
+#define TCTRL4_RD_WR_PI_MORE_DLY 0x000007c000000000UL
+#define TCTRL4_RD_WR_PI_MORE_DLY_SHIFT 38
+#define TCTRL4_RD_WR_TI_DLY 0x0000003f00000000UL
+#define TCTRL4_RD_WR_TI_DLY_SHIFT 32
+#define TCTRL4_WR_WR_PI_MORE_DLY 0x00000000f8000000UL
+#define TCTRL4_WR_WR_PI_MORE_DLY_SHIFT 27
+#define TCTRL4_WR_WR_TI_DLY 0x0000000007e00000UL
+#define TCTRL4_WR_WR_TI_DLY_SHIFT 21
+#define TCTRL4_RDWR_RD_PI_MORE_DLY 0x00000000001f000UL0
+#define TCTRL4_RDWR_RD_PI_MORE_DLY_SHIFT 16
+#define TCTRL4_R 0x0000000000008000UL
+#define TCTRL4_R_SHIFT 15
+#define TCTRL4_SDRAM_MODE_REG_DATA 0x0000000000007fffUL
+#define TCTRL4_SDRAM_MODE_REG_DATA_SHIFT 0
+
+/* All 4 memory address decoding registers have the
+ * same layout.
+ */
+#define MEM_DECODE_VALID 0x8000000000000000UL /* Valid */
+#define MEM_DECODE_VALID_SHIFT 63
+#define MEM_DECODE_UK 0x001ffe0000000000UL /* Upper mask */
+#define MEM_DECODE_UK_SHIFT 41
+#define MEM_DECODE_UM 0x0000001ffff00000UL /* Upper match */
+#define MEM_DECODE_UM_SHIFT 20
+#define MEM_DECODE_LK 0x000000000003c000UL /* Lower mask */
+#define MEM_DECODE_LK_SHIFT 14
+#define MEM_DECODE_LM 0x0000000000000f00UL /* Lower match */
+#define MEM_DECODE_LM_SHIFT 8
+
+#define PA_UPPER_BITS 0x000007fffc000000UL
+#define PA_UPPER_BITS_SHIFT 26
+#define PA_LOWER_BITS 0x00000000000003c0UL
+#define PA_LOWER_BITS_SHIFT 6
+
+#define MACTRL_R0 0x8000000000000000UL
+#define MACTRL_R0_SHIFT 63
+#define MACTRL_ADDR_LE_PW 0x7000000000000000UL
+#define MACTRL_ADDR_LE_PW_SHIFT 60
+#define MACTRL_CMD_PW 0x0f00000000000000UL
+#define MACTRL_CMD_PW_SHIFT 56
+#define MACTRL_HALF_MODE_WR_MSEL_DLY 0x00fc000000000000UL
+#define MACTRL_HALF_MODE_WR_MSEL_DLY_SHIFT 50
+#define MACTRL_HALF_MODE_RD_MSEL_DLY 0x0003f00000000000UL
+#define MACTRL_HALF_MODE_RD_MSEL_DLY_SHIFT 44
+#define MACTRL_HALF_MODE_SDRAM_CTL_DLY 0x00000f0000000000UL
+#define MACTRL_HALF_MODE_SDRAM_CTL_DLY_SHIFT 40
+#define MACTRL_HALF_MODE_SDRAM_CLK_DLY 0x000000e000000000UL
+#define MACTRL_HALF_MODE_SDRAM_CLK_DLY_SHIFT 37
+#define MACTRL_R1 0x0000001000000000UL
+#define MACTRL_R1_SHIFT 36
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B3 0x0000000f00000000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B3_SHIFT 32
+#define MACTRL_ENC_INTLV_B3 0x00000000f8000000UL
+#define MACTRL_ENC_INTLV_B3_SHIFT 27
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B2 0x0000000007800000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B2_SHIFT 23
+#define MACTRL_ENC_INTLV_B2 0x00000000007c0000UL
+#define MACTRL_ENC_INTLV_B2_SHIFT 18
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B1 0x000000000003c000UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B1_SHIFT 14
+#define MACTRL_ENC_INTLV_B1 0x0000000000003e00UL
+#define MACTRL_ENC_INTLV_B1_SHIFT 9
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B0 0x00000000000001e0UL
+#define MACTRL_BANKSEL_N_ROWADDR_SIZE_B0_SHIFT 5
+#define MACTRL_ENC_INTLV_B0 0x000000000000001fUL
+#define MACTRL_ENC_INTLV_B0_SHIFT 0
+
+#endif /* _SPARC64_CHMCTRL_H */
diff --git a/arch/sparc/include/asm/clock.h b/arch/sparc/include/asm/clock.h
new file mode 100644
index 000000000..2cf99dade
--- /dev/null
+++ b/arch/sparc/include/asm/clock.h
@@ -0,0 +1,11 @@
+/*
+ * clock.h: Definitions for clock operations on the Sparc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_CLOCK_H
+#define _SPARC_CLOCK_H
+
+/* Foo for now. */
+
+#endif /* !(_SPARC_CLOCK_H) */
diff --git a/arch/sparc/include/asm/clocksource.h b/arch/sparc/include/asm/clocksource.h
new file mode 100644
index 000000000..d63ef224b
--- /dev/null
+++ b/arch/sparc/include/asm/clocksource.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _ASM_SPARC_CLOCKSOURCE_H
+#define _ASM_SPARC_CLOCKSOURCE_H
+
+/* VDSO clocksources */
+#define VCLOCK_NONE 0 /* Nothing userspace can do. */
+#define VCLOCK_TICK 1 /* Use %tick. */
+#define VCLOCK_STICK 2 /* Use %stick. */
+
+struct arch_clocksource_data {
+ int vclock_mode;
+};
+
+#endif /* _ASM_SPARC_CLOCKSOURCE_H */
diff --git a/arch/sparc/include/asm/cmpxchg.h b/arch/sparc/include/asm/cmpxchg.h
new file mode 100644
index 000000000..b7955c6b9
--- /dev/null
+++ b/arch/sparc/include/asm/cmpxchg.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_CMPXCHG_H
+#define ___ASM_SPARC_CMPXCHG_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/cmpxchg_64.h>
+#else
+#include <asm/cmpxchg_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/cmpxchg_32.h b/arch/sparc/include/asm/cmpxchg_32.h
new file mode 100644
index 000000000..d0af82c24
--- /dev/null
+++ b/arch/sparc/include/asm/cmpxchg_32.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* 32-bit atomic xchg() and cmpxchg() definitions.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ * Copyright (C) 2007 Kyle McMartin (kyle@parisc-linux.org)
+ *
+ * Additions by Keith M Wesolowski (wesolows@foobazco.org) based
+ * on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>.
+ */
+
+#ifndef __ARCH_SPARC_CMPXCHG__
+#define __ARCH_SPARC_CMPXCHG__
+
+unsigned long __xchg_u32(volatile u32 *m, u32 new);
+void __xchg_called_with_bad_pointer(void);
+
+static __always_inline unsigned long __arch_xchg(unsigned long x, __volatile__ void * ptr, int size)
+{
+ switch (size) {
+ case 4:
+ return __xchg_u32(ptr, x);
+ }
+ __xchg_called_with_bad_pointer();
+ return x;
+}
+
+#define arch_xchg(ptr,x) ({(__typeof__(*(ptr)))__arch_xchg((unsigned long)(x),(ptr),sizeof(*(ptr)));})
+
+/* Emulate cmpxchg() the same way we emulate atomics,
+ * by hashing the object address and indexing into an array
+ * of spinlocks to get a bit of performance...
+ *
+ * See arch/sparc/lib/atomic32.c for implementation.
+ *
+ * Cribbed from <asm-parisc/atomic.h>
+ */
+
+/* bug catcher for when unsupported size is used - won't link */
+void __cmpxchg_called_with_bad_pointer(void);
+/* we only need to support cmpxchg of a u32 on sparc */
+unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
+
+/* don't worry...optimizer will get rid of most of this */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
+{
+ switch (size) {
+ case 4:
+ return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
+ default:
+ __cmpxchg_called_with_bad_pointer();
+ break;
+ }
+ return old;
+}
+
+#define arch_cmpxchg(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof(*(ptr))); \
+})
+
+u64 __cmpxchg_u64(u64 *ptr, u64 old, u64 new);
+#define arch_cmpxchg64(ptr, old, new) __cmpxchg_u64(ptr, old, new)
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define arch_cmpxchg_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))__generic_cmpxchg_local((ptr), (unsigned long)(o),\
+ (unsigned long)(n), sizeof(*(ptr))))
+#define arch_cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n))
+
+#endif /* __ARCH_SPARC_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/cmpxchg_64.h b/arch/sparc/include/asm/cmpxchg_64.h
new file mode 100644
index 000000000..3de25262c
--- /dev/null
+++ b/arch/sparc/include/asm/cmpxchg_64.h
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* 64-bit atomic xchg() and cmpxchg() definitions.
+ *
+ * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __ARCH_SPARC64_CMPXCHG__
+#define __ARCH_SPARC64_CMPXCHG__
+
+static inline unsigned long
+__cmpxchg_u32(volatile int *m, int old, int new)
+{
+ __asm__ __volatile__("cas [%2], %3, %0"
+ : "=&r" (new)
+ : "0" (new), "r" (m), "r" (old)
+ : "memory");
+
+ return new;
+}
+
+static inline unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
+{
+ unsigned long tmp1, tmp2;
+
+ __asm__ __volatile__(
+" mov %0, %1\n"
+"1: lduw [%4], %2\n"
+" cas [%4], %2, %0\n"
+" cmp %2, %0\n"
+" bne,a,pn %%icc, 1b\n"
+" mov %1, %0\n"
+ : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+ : "0" (val), "r" (m)
+ : "cc", "memory");
+ return val;
+}
+
+static inline unsigned long xchg64(__volatile__ unsigned long *m, unsigned long val)
+{
+ unsigned long tmp1, tmp2;
+
+ __asm__ __volatile__(
+" mov %0, %1\n"
+"1: ldx [%4], %2\n"
+" casx [%4], %2, %0\n"
+" cmp %2, %0\n"
+" bne,a,pn %%xcc, 1b\n"
+" mov %1, %0\n"
+ : "=&r" (val), "=&r" (tmp1), "=&r" (tmp2)
+ : "0" (val), "r" (m)
+ : "cc", "memory");
+ return val;
+}
+
+#define arch_xchg(ptr,x) \
+({ __typeof__(*(ptr)) __ret; \
+ __ret = (__typeof__(*(ptr))) \
+ __arch_xchg((unsigned long)(x), (ptr), sizeof(*(ptr))); \
+ __ret; \
+})
+
+void __xchg_called_with_bad_pointer(void);
+
+/*
+ * Use 4 byte cas instruction to achieve 2 byte xchg. Main logic
+ * here is to get the bit shift of the byte we are interested in.
+ * The XOR is handy for reversing the bits for big-endian byte order.
+ */
+static inline unsigned long
+xchg16(__volatile__ unsigned short *m, unsigned short val)
+{
+ unsigned long maddr = (unsigned long)m;
+ int bit_shift = (((unsigned long)m & 2) ^ 2) << 3;
+ unsigned int mask = 0xffff << bit_shift;
+ unsigned int *ptr = (unsigned int *) (maddr & ~2);
+ unsigned int old32, new32, load32;
+
+ /* Read the old value */
+ load32 = *ptr;
+
+ do {
+ old32 = load32;
+ new32 = (load32 & (~mask)) | val << bit_shift;
+ load32 = __cmpxchg_u32(ptr, old32, new32);
+ } while (load32 != old32);
+
+ return (load32 & mask) >> bit_shift;
+}
+
+static __always_inline unsigned long
+__arch_xchg(unsigned long x, __volatile__ void * ptr, int size)
+{
+ switch (size) {
+ case 2:
+ return xchg16(ptr, x);
+ case 4:
+ return xchg32(ptr, x);
+ case 8:
+ return xchg64(ptr, x);
+ }
+ __xchg_called_with_bad_pointer();
+ return x;
+}
+
+/*
+ * Atomic compare and exchange. Compare OLD with MEM, if identical,
+ * store NEW in MEM. Return the initial value in MEM. Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#include <asm-generic/cmpxchg-local.h>
+
+
+static inline unsigned long
+__cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new)
+{
+ __asm__ __volatile__("casx [%2], %3, %0"
+ : "=&r" (new)
+ : "0" (new), "r" (m), "r" (old)
+ : "memory");
+
+ return new;
+}
+
+/*
+ * Use 4 byte cas instruction to achieve 1 byte cmpxchg. Main logic
+ * here is to get the bit shift of the byte we are interested in.
+ * The XOR is handy for reversing the bits for big-endian byte order
+ */
+static inline unsigned long
+__cmpxchg_u8(volatile unsigned char *m, unsigned char old, unsigned char new)
+{
+ unsigned long maddr = (unsigned long)m;
+ int bit_shift = (((unsigned long)m & 3) ^ 3) << 3;
+ unsigned int mask = 0xff << bit_shift;
+ unsigned int *ptr = (unsigned int *) (maddr & ~3);
+ unsigned int old32, new32, load;
+ unsigned int load32 = *ptr;
+
+ do {
+ new32 = (load32 & ~mask) | (new << bit_shift);
+ old32 = (load32 & ~mask) | (old << bit_shift);
+ load32 = __cmpxchg_u32(ptr, old32, new32);
+ if (load32 == old32)
+ return old;
+ load = (load32 & mask) >> bit_shift;
+ } while (load == old);
+
+ return load;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+ if something tries to do an invalid cmpxchg(). */
+void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+ switch (size) {
+ case 1:
+ return __cmpxchg_u8(ptr, old, new);
+ case 4:
+ return __cmpxchg_u32(ptr, old, new);
+ case 8:
+ return __cmpxchg_u64(ptr, old, new);
+ }
+ __cmpxchg_called_with_bad_pointer();
+ return old;
+}
+
+#define arch_cmpxchg(ptr,o,n) \
+ ({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof(*(ptr))); \
+ })
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+ unsigned long old,
+ unsigned long new, int size)
+{
+ switch (size) {
+ case 4:
+ case 8: return __cmpxchg(ptr, old, new, size);
+ default:
+ return __generic_cmpxchg_local(ptr, old, new, size);
+ }
+
+ return old;
+}
+
+#define arch_cmpxchg_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+ (unsigned long)(n), sizeof(*(ptr))))
+#define arch_cmpxchg64_local(ptr, o, n) \
+ ({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ arch_cmpxchg_local((ptr), (o), (n)); \
+ })
+#define arch_cmpxchg64(ptr, o, n) arch_cmpxchg64_local((ptr), (o), (n))
+
+#endif /* __ARCH_SPARC64_CMPXCHG__ */
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
new file mode 100644
index 000000000..e4382d2ef
--- /dev/null
+++ b/arch/sparc/include/asm/compat.h
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC64_COMPAT_H
+#define _ASM_SPARC64_COMPAT_H
+/*
+ * Architecture specific compatibility types
+ */
+#include <linux/types.h>
+
+#define compat_mode_t compat_mode_t
+typedef u16 compat_mode_t;
+
+#define __compat_uid_t __compat_uid_t
+typedef u16 __compat_uid_t;
+typedef u16 __compat_gid_t;
+
+#define compat_dev_t compat_dev_t
+typedef u16 compat_dev_t;
+
+#define compat_ipc_pid_t compat_ipc_pid_t
+typedef u16 compat_ipc_pid_t;
+
+#define compat_ipc64_perm compat_ipc64_perm
+
+#define COMPAT_RLIM_INFINITY 0x7fffffff
+
+#include <asm-generic/compat.h>
+
+#define COMPAT_UTS_MACHINE "sparc\0\0"
+
+typedef s16 compat_nlink_t;
+
+struct compat_stat {
+ compat_dev_t st_dev;
+ compat_ino_t st_ino;
+ compat_mode_t st_mode;
+ compat_nlink_t st_nlink;
+ __compat_uid_t st_uid;
+ __compat_gid_t st_gid;
+ compat_dev_t st_rdev;
+ compat_off_t st_size;
+ old_time32_t st_atime;
+ compat_ulong_t st_atime_nsec;
+ old_time32_t st_mtime;
+ compat_ulong_t st_mtime_nsec;
+ old_time32_t st_ctime;
+ compat_ulong_t st_ctime_nsec;
+ compat_off_t st_blksize;
+ compat_off_t st_blocks;
+ u32 __unused4[2];
+};
+
+struct compat_stat64 {
+ unsigned long long st_dev;
+
+ unsigned long long st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ unsigned int st_uid;
+ unsigned int st_gid;
+
+ unsigned long long st_rdev;
+
+ unsigned char __pad3[8];
+
+ long long st_size;
+ unsigned int st_blksize;
+
+ unsigned char __pad4[8];
+ unsigned int st_blocks;
+
+ unsigned int st_atime;
+ unsigned int st_atime_nsec;
+
+ unsigned int st_mtime;
+ unsigned int st_mtime_nsec;
+
+ unsigned int st_ctime;
+ unsigned int st_ctime_nsec;
+
+ unsigned int __unused4;
+ unsigned int __unused5;
+};
+
+#define __ARCH_COMPAT_FLOCK_PAD short __unused;
+
+struct compat_ipc64_perm {
+ compat_key_t key;
+ __compat_uid32_t uid;
+ __compat_gid32_t gid;
+ __compat_uid32_t cuid;
+ __compat_gid32_t cgid;
+ unsigned short __pad1;
+ compat_mode_t mode;
+ unsigned short __pad2;
+ unsigned short seq;
+ unsigned long __unused1; /* yes they really are 64bit pads */
+ unsigned long __unused2;
+};
+
+struct compat_semid64_ds {
+ struct compat_ipc64_perm sem_perm;
+ unsigned int sem_otime_high;
+ unsigned int sem_otime;
+ unsigned int sem_ctime_high;
+ unsigned int sem_ctime;
+ u32 sem_nsems;
+ u32 __unused1;
+ u32 __unused2;
+};
+
+struct compat_msqid64_ds {
+ struct compat_ipc64_perm msg_perm;
+ unsigned int msg_stime_high;
+ unsigned int msg_stime;
+ unsigned int msg_rtime_high;
+ unsigned int msg_rtime;
+ unsigned int msg_ctime_high;
+ unsigned int msg_ctime;
+ unsigned int msg_cbytes;
+ unsigned int msg_qnum;
+ unsigned int msg_qbytes;
+ compat_pid_t msg_lspid;
+ compat_pid_t msg_lrpid;
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+struct compat_shmid64_ds {
+ struct compat_ipc64_perm shm_perm;
+ unsigned int shm_atime_high;
+ unsigned int shm_atime;
+ unsigned int shm_dtime_high;
+ unsigned int shm_dtime;
+ unsigned int shm_ctime_high;
+ unsigned int shm_ctime;
+ compat_size_t shm_segsz;
+ compat_pid_t shm_cpid;
+ compat_pid_t shm_lpid;
+ unsigned int shm_nattch;
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
+#ifdef CONFIG_COMPAT
+static inline int is_compat_task(void)
+{
+ return test_thread_flag(TIF_32BIT);
+}
+
+static inline bool in_compat_syscall(void)
+{
+ /* Vector 0x110 is LINUX_32BIT_SYSCALL_TRAP */
+ return pt_regs_trap_type(current_pt_regs()) == 0x110;
+}
+#define in_compat_syscall in_compat_syscall
+#endif
+
+#endif /* _ASM_SPARC64_COMPAT_H */
diff --git a/arch/sparc/include/asm/compat_signal.h b/arch/sparc/include/asm/compat_signal.h
new file mode 100644
index 000000000..e5f7a7f28
--- /dev/null
+++ b/arch/sparc/include/asm/compat_signal.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _COMPAT_SIGNAL_H
+#define _COMPAT_SIGNAL_H
+
+#include <linux/compat.h>
+#include <asm/signal.h>
+
+#ifdef CONFIG_COMPAT
+struct __new_sigaction32 {
+ unsigned int sa_handler;
+ unsigned int sa_flags;
+ unsigned int sa_restorer; /* not used by Linux/SPARC yet */
+ compat_sigset_t sa_mask;
+};
+
+struct __old_sigaction32 {
+ unsigned int sa_handler;
+ compat_old_sigset_t sa_mask;
+ unsigned int sa_flags;
+ unsigned int sa_restorer; /* not used by Linux/SPARC yet */
+};
+#endif
+
+#endif /* !(_COMPAT_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/contregs.h b/arch/sparc/include/asm/contregs.h
new file mode 100644
index 000000000..4df56a6ba
--- /dev/null
+++ b/arch/sparc/include/asm/contregs.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_CONTREGS_H
+#define _SPARC_CONTREGS_H
+
+/* contregs.h: Addresses of registers in the ASI_CONTROL alternate address
+ * space. These are for the mmu's context register, etc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress */
+#define AC_M_PCR 0x0000 /* shv Processor Control Reg */
+#define AC_M_CTPR 0x0100 /* shv Context Table Pointer Reg */
+#define AC_M_CXR 0x0200 /* shv Context Register */
+#define AC_M_SFSR 0x0300 /* shv Synchronous Fault Status Reg */
+#define AC_M_SFAR 0x0400 /* shv Synchronous Fault Address Reg */
+#define AC_M_AFSR 0x0500 /* hv Asynchronous Fault Status Reg */
+#define AC_M_AFAR 0x0600 /* hv Asynchronous Fault Address Reg */
+#define AC_M_RESET 0x0700 /* hv Reset Reg */
+#define AC_M_RPR 0x1000 /* hv Root Pointer Reg */
+#define AC_M_TSUTRCR 0x1000 /* s TLB Replacement Ctrl Reg */
+#define AC_M_IAPTP 0x1100 /* hv Instruction Access PTP */
+#define AC_M_DAPTP 0x1200 /* hv Data Access PTP */
+#define AC_M_ITR 0x1300 /* hv Index Tag Register */
+#define AC_M_TRCR 0x1400 /* hv TLB Replacement Control Reg */
+#define AC_M_SFSRX 0x1300 /* s Synch Fault Status Reg prim */
+#define AC_M_SFARX 0x1400 /* s Synch Fault Address Reg prim */
+#define AC_M_RPR1 0x1500 /* h Root Pointer Reg (entry 2) */
+#define AC_M_IAPTP1 0x1600 /* h Instruction Access PTP (entry 2) */
+#define AC_M_DAPTP1 0x1700 /* h Data Access PTP (entry 2) */
+
+#endif /* _SPARC_CONTREGS_H */
diff --git a/arch/sparc/include/asm/cpu_type.h b/arch/sparc/include/asm/cpu_type.h
new file mode 100644
index 000000000..2b5979985
--- /dev/null
+++ b/arch/sparc/include/asm/cpu_type.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_CPU_TYPE_H
+#define __ASM_CPU_TYPE_H
+
+/*
+ * Sparc (general) CPU types
+ */
+enum sparc_cpu {
+ sun4m = 0x00,
+ sun4d = 0x01,
+ sun4e = 0x02,
+ sun4u = 0x03, /* V8 ploos ploos */
+ sun_unknown = 0x04,
+ ap1000 = 0x05, /* almost a sun4m */
+ sparc_leon = 0x06, /* Leon SoC */
+};
+
+#ifdef CONFIG_SPARC32
+extern enum sparc_cpu sparc_cpu_model;
+
+#define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */
+
+#else
+
+#define sparc_cpu_model sun4u
+
+#endif
+
+#endif /* __ASM_CPU_TYPE_H */
diff --git a/arch/sparc/include/asm/cpudata.h b/arch/sparc/include/asm/cpudata.h
new file mode 100644
index 000000000..d213165ee
--- /dev/null
+++ b/arch/sparc/include/asm/cpudata.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_CPUDATA_H
+#define ___ASM_SPARC_CPUDATA_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/threads.h>
+#include <linux/percpu.h>
+
+extern const struct seq_operations cpuinfo_op;
+
+#endif /* !(__ASSEMBLY__) */
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/cpudata_64.h>
+#else
+#include <asm/cpudata_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/cpudata_32.h b/arch/sparc/include/asm/cpudata_32.h
new file mode 100644
index 000000000..895d0964b
--- /dev/null
+++ b/arch/sparc/include/asm/cpudata_32.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* cpudata.h: Per-cpu parameters.
+ *
+ * Copyright (C) 2004 Keith M Wesolowski (wesolows@foobazco.org)
+ *
+ * Based on include/asm/cpudata.h and Linux 2.4 smp.h
+ * both (C) David S. Miller.
+ */
+
+#ifndef _SPARC_CPUDATA_H
+#define _SPARC_CPUDATA_H
+
+#include <linux/percpu.h>
+
+typedef struct {
+ unsigned long udelay_val;
+ unsigned long clock_tick;
+ unsigned int counter;
+#ifdef CONFIG_SMP
+ unsigned int irq_resched_count;
+ unsigned int irq_call_count;
+#endif
+ int prom_node;
+ int mid;
+ int next;
+} cpuinfo_sparc;
+
+DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
+#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
+#define local_cpu_data() (*this_cpu_ptr(&__cpu_data))
+
+#endif /* _SPARC_CPUDATA_H */
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h
new file mode 100644
index 000000000..9c3fc03ab
--- /dev/null
+++ b/arch/sparc/include/asm/cpudata_64.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* cpudata.h: Per-cpu parameters.
+ *
+ * Copyright (C) 2003, 2005, 2006 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_CPUDATA_H
+#define _SPARC64_CPUDATA_H
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+ /* Dcache line 1 */
+ unsigned int __softirq_pending; /* must be 1st, see rtrap.S */
+ unsigned int __nmi_count;
+ unsigned long clock_tick; /* %tick's per second */
+ unsigned long __pad;
+ unsigned int irq0_irqs;
+ unsigned int __pad2;
+
+ /* Dcache line 2, rarely used */
+ unsigned int dcache_size;
+ unsigned int dcache_line_size;
+ unsigned int icache_size;
+ unsigned int icache_line_size;
+ unsigned int ecache_size;
+ unsigned int ecache_line_size;
+ unsigned short sock_id; /* physical package */
+ unsigned short core_id;
+ unsigned short max_cache_id; /* groupings of highest shared cache */
+ signed short proc_id; /* strand (aka HW thread) id */
+} cpuinfo_sparc;
+
+DECLARE_PER_CPU(cpuinfo_sparc, __cpu_data);
+#define cpu_data(__cpu) per_cpu(__cpu_data, (__cpu))
+#define local_cpu_data() (*this_cpu_ptr(&__cpu_data))
+
+#endif /* !(__ASSEMBLY__) */
+
+#include <asm/trap_block.h>
+
+#endif /* _SPARC64_CPUDATA_H */
diff --git a/arch/sparc/include/asm/current.h b/arch/sparc/include/asm/current.h
new file mode 100644
index 000000000..c68312a89
--- /dev/null
+++ b/arch/sparc/include/asm/current.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* include/asm/current.h
+ *
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 2002 Pete Zaitcev (zaitcev@yahoo.com)
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ *
+ * Derived from "include/asm-s390/current.h" by
+ * Martin Schwidefsky (schwidefsky@de.ibm.com)
+ * Derived from "include/asm-i386/current.h"
+*/
+#ifndef _SPARC_CURRENT_H
+#define _SPARC_CURRENT_H
+
+#include <linux/thread_info.h>
+
+#ifdef CONFIG_SPARC64
+register struct task_struct *current asm("g4");
+#endif
+
+#ifdef CONFIG_SPARC32
+/* We might want to consider using %g4 like sparc64 to shave a few cycles.
+ *
+ * Two stage process (inline + #define) for type-checking.
+ * We also obfuscate get_current() to check if anyone used that by mistake.
+ */
+struct task_struct;
+static inline struct task_struct *__get_current(void)
+{
+ return current_thread_info()->task;
+}
+#define current __get_current()
+#endif
+
+#endif /* !(_SPARC_CURRENT_H) */
diff --git a/arch/sparc/include/asm/dcr.h b/arch/sparc/include/asm/dcr.h
new file mode 100644
index 000000000..c810e1b42
--- /dev/null
+++ b/arch/sparc/include/asm/dcr.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_DCR_H
+#define _SPARC64_DCR_H
+
+/* UltraSparc-III/III+ Dispatch Control Register, ASR 0x12 */
+#define DCR_DPE 0x0000000000001000 /* III+: D$ Parity Error Enable */
+#define DCR_OBS 0x0000000000000fc0 /* Observability Bus Controls */
+#define DCR_BPE 0x0000000000000020 /* Branch Predict Enable */
+#define DCR_RPE 0x0000000000000010 /* Return Address Prediction Enable */
+#define DCR_SI 0x0000000000000008 /* Single Instruction Disable */
+#define DCR_IPE 0x0000000000000004 /* III+: I$ Parity Error Enable */
+#define DCR_IFPOE 0x0000000000000002 /* IRQ FP Operation Enable */
+#define DCR_MS 0x0000000000000001 /* Multi-Scalar dispatch */
+
+#endif /* _SPARC64_DCR_H */
diff --git a/arch/sparc/include/asm/dcu.h b/arch/sparc/include/asm/dcu.h
new file mode 100644
index 000000000..93f325071
--- /dev/null
+++ b/arch/sparc/include/asm/dcu.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_DCU_H
+#define _SPARC64_DCU_H
+
+#include <linux/const.h>
+
+/* UltraSparc-III Data Cache Unit Control Register */
+#define DCU_CP _AC(0x0002000000000000,UL) /* Phys Cache Enable w/o mmu */
+#define DCU_CV _AC(0x0001000000000000,UL) /* Virt Cache Enable w/o mmu */
+#define DCU_ME _AC(0x0000800000000000,UL) /* NC-store Merging Enable */
+#define DCU_RE _AC(0x0000400000000000,UL) /* RAW bypass Enable */
+#define DCU_PE _AC(0x0000200000000000,UL) /* PCache Enable */
+#define DCU_HPE _AC(0x0000100000000000,UL) /* HW prefetch Enable */
+#define DCU_SPE _AC(0x0000080000000000,UL) /* SW prefetch Enable */
+#define DCU_SL _AC(0x0000040000000000,UL) /* Secondary ld-steering Enab*/
+#define DCU_WE _AC(0x0000020000000000,UL) /* WCache enable */
+#define DCU_PM _AC(0x000001fe00000000,UL) /* PA Watchpoint Byte Mask */
+#define DCU_VM _AC(0x00000001fe000000,UL) /* VA Watchpoint Byte Mask */
+#define DCU_PR _AC(0x0000000001000000,UL) /* PA Watchpoint Read Enable */
+#define DCU_PW _AC(0x0000000000800000,UL) /* PA Watchpoint Write Enable*/
+#define DCU_VR _AC(0x0000000000400000,UL) /* VA Watchpoint Read Enable */
+#define DCU_VW _AC(0x0000000000200000,UL) /* VA Watchpoint Write Enable*/
+#define DCU_DM _AC(0x0000000000000008,UL) /* DMMU Enable */
+#define DCU_IM _AC(0x0000000000000004,UL) /* IMMU Enable */
+#define DCU_DC _AC(0x0000000000000002,UL) /* Data Cache Enable */
+#define DCU_IC _AC(0x0000000000000001,UL) /* Instruction Cache Enable */
+
+#endif /* _SPARC64_DCU_H */
diff --git a/arch/sparc/include/asm/delay.h b/arch/sparc/include/asm/delay.h
new file mode 100644
index 000000000..c96af9b91
--- /dev/null
+++ b/arch/sparc/include/asm/delay.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_DELAY_H
+#define ___ASM_SPARC_DELAY_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/delay_64.h>
+#else
+#include <asm/delay_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/delay_32.h b/arch/sparc/include/asm/delay_32.h
new file mode 100644
index 000000000..0e6dfe857
--- /dev/null
+++ b/arch/sparc/include/asm/delay_32.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * delay.h: Linux delay routines on the Sparc.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu).
+ */
+
+#ifndef __SPARC_DELAY_H
+#define __SPARC_DELAY_H
+
+#include <asm/cpudata.h>
+
+static inline void __delay(unsigned long loops)
+{
+ __asm__ __volatile__("cmp %0, 0\n\t"
+ "1: bne 1b\n\t"
+ "subcc %0, 1, %0\n" :
+ "=&r" (loops) :
+ "0" (loops) :
+ "cc");
+}
+
+/* This is too messy with inline asm on the Sparc. */
+void __udelay(unsigned long usecs, unsigned long lpj);
+void __ndelay(unsigned long nsecs, unsigned long lpj);
+
+#ifdef CONFIG_SMP
+#define __udelay_val cpu_data(smp_processor_id()).udelay_val
+#else /* SMP */
+#define __udelay_val loops_per_jiffy
+#endif /* SMP */
+#define udelay(__usecs) __udelay(__usecs, __udelay_val)
+#define ndelay(__nsecs) __ndelay(__nsecs, __udelay_val)
+
+#endif /* defined(__SPARC_DELAY_H) */
diff --git a/arch/sparc/include/asm/delay_64.h b/arch/sparc/include/asm/delay_64.h
new file mode 100644
index 000000000..22213b1c1
--- /dev/null
+++ b/arch/sparc/include/asm/delay_64.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* delay.h: Linux delay routines on sparc64.
+ *
+ * Copyright (C) 1996, 2004, 2007 David S. Miller (davem@davemloft.net).
+ */
+
+#ifndef _SPARC64_DELAY_H
+#define _SPARC64_DELAY_H
+
+#ifndef __ASSEMBLY__
+
+void __delay(unsigned long loops);
+void udelay(unsigned long usecs);
+#define mdelay(n) udelay((n) * 1000)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _SPARC64_DELAY_H */
diff --git a/arch/sparc/include/asm/device.h b/arch/sparc/include/asm/device.h
new file mode 100644
index 000000000..a797d5e86
--- /dev/null
+++ b/arch/sparc/include/asm/device.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Arch specific extensions to struct device
+ */
+#ifndef _ASM_SPARC_DEVICE_H
+#define _ASM_SPARC_DEVICE_H
+
+#include <asm/openprom.h>
+
+struct device_node;
+struct platform_device;
+
+struct dev_archdata {
+ void *iommu;
+ void *stc;
+ void *host_controller;
+ struct platform_device *op;
+ int numa_node;
+};
+
+void of_propagate_archdata(struct platform_device *bus);
+
+struct pdev_archdata {
+ struct resource resource[PROMREG_MAX];
+ unsigned int irqs[PROMINTR_MAX];
+ int num_irqs;
+};
+
+#endif /* _ASM_SPARC_DEVICE_H */
diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h
new file mode 100644
index 000000000..55c12fc2b
--- /dev/null
+++ b/arch/sparc/include/asm/dma-mapping.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_DMA_MAPPING_H
+#define ___ASM_SPARC_DMA_MAPPING_H
+
+extern const struct dma_map_ops *dma_ops;
+
+static inline const struct dma_map_ops *get_arch_dma_ops(void)
+{
+ /* sparc32 uses per-device dma_ops */
+ return IS_ENABLED(CONFIG_SPARC64) ? dma_ops : NULL;
+}
+
+#endif
diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h
new file mode 100644
index 000000000..08043f35b
--- /dev/null
+++ b/arch/sparc/include/asm/dma.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC_DMA_H
+#define _ASM_SPARC_DMA_H
+
+/* These are irrelevant for Sparc DMA, but we leave it in so that
+ * things can compile.
+ */
+#define MAX_DMA_CHANNELS 8
+#define DMA_MODE_READ 1
+#define DMA_MODE_WRITE 2
+#define MAX_DMA_ADDRESS (~0UL)
+
+/* Useful constants */
+#define SIZE_16MB (16*1024*1024)
+#define SIZE_64K (64*1024)
+
+/* SBUS DMA controller reg offsets */
+#define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */
+#define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */
+#define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */
+#define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */
+
+/* Fields in the cond_reg register */
+/* First, the version identification bits */
+#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */
+#define DMA_VERS0 0x00000000 /* Sunray DMA version */
+#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */
+#define DMA_VERS1 0x80000000 /* DMA rev 1 */
+#define DMA_VERS2 0xa0000000 /* DMA rev 2 */
+#define DMA_VERHME 0xb0000000 /* DMA hme gate array */
+#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */
+
+#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */
+#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */
+#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */
+#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */
+#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */
+#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */
+#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */
+#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */
+#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */
+#define DMA_ST_WRITE 0x00000100 /* write from device to memory */
+#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */
+#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */
+#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */
+#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */
+#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */
+#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */
+#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */
+#define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */
+#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */
+#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */
+#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */
+#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */
+#define DMA_E_BURSTS 0x000c0000 /* ENET: SBUS r/w burst mask */
+#define DMA_E_BURST32 0x00040000 /* ENET: SBUS 32 byte r/w burst */
+#define DMA_E_BURST16 0x00000000 /* ENET: SBUS 16 byte r/w burst */
+#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */
+#define DMA_BRST64 0x000c0000 /* SCSI: 64byte bursts (HME on UltraSparc only) */
+#define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */
+#define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */
+#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */
+#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */
+#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */
+#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */
+#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */
+#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */
+#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */
+#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */
+#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */
+#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */
+#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */
+#define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */
+
+/* Values describing the burst-size property from the PROM */
+#define DMA_BURST1 0x01
+#define DMA_BURST2 0x02
+#define DMA_BURST4 0x04
+#define DMA_BURST8 0x08
+#define DMA_BURST16 0x10
+#define DMA_BURST32 0x20
+#define DMA_BURST64 0x40
+#define DMA_BURSTBITS 0x7f
+
+#ifdef CONFIG_SPARC32
+struct device;
+
+unsigned long sparc_dma_alloc_resource(struct device *dev, size_t len);
+bool sparc_dma_free_resource(void *cpu_addr, size_t size);
+#endif
+
+#endif /* !(_ASM_SPARC_DMA_H) */
diff --git a/arch/sparc/include/asm/ebus_dma.h b/arch/sparc/include/asm/ebus_dma.h
new file mode 100644
index 000000000..75563ed09
--- /dev/null
+++ b/arch/sparc/include/asm/ebus_dma.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_SPARC_EBUS_DMA_H
+#define __ASM_SPARC_EBUS_DMA_H
+
+struct ebus_dma_info {
+ spinlock_t lock;
+ void __iomem *regs;
+
+ unsigned int flags;
+#define EBUS_DMA_FLAG_USE_EBDMA_HANDLER 0x00000001
+#define EBUS_DMA_FLAG_TCI_DISABLE 0x00000002
+
+ /* These are only valid is EBUS_DMA_FLAG_USE_EBDMA_HANDLER is
+ * set.
+ */
+ void (*callback)(struct ebus_dma_info *p, int event, void *cookie);
+ void *client_cookie;
+ unsigned int irq;
+#define EBUS_DMA_EVENT_ERROR 1
+#define EBUS_DMA_EVENT_DMA 2
+#define EBUS_DMA_EVENT_DEVICE 4
+
+ unsigned char name[64];
+};
+
+int ebus_dma_register(struct ebus_dma_info *p);
+int ebus_dma_irq_enable(struct ebus_dma_info *p, int on);
+void ebus_dma_unregister(struct ebus_dma_info *p);
+int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr,
+ size_t len);
+void ebus_dma_prepare(struct ebus_dma_info *p, int write);
+unsigned int ebus_dma_residue(struct ebus_dma_info *p);
+unsigned int ebus_dma_addr(struct ebus_dma_info *p);
+void ebus_dma_enable(struct ebus_dma_info *p, int on);
+
+#endif /* __ASM_SPARC_EBUS_DMA_H */
diff --git a/arch/sparc/include/asm/ecc.h b/arch/sparc/include/asm/ecc.h
new file mode 100644
index 000000000..3d5edee36
--- /dev/null
+++ b/arch/sparc/include/asm/ecc.h
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ecc.h: Definitions and defines for the external cache/memory
+ * controller on the sun4m.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_ECC_H
+#define _SPARC_ECC_H
+
+/* These registers are accessed through the SRMMU passthrough ASI 0x20 */
+#define ECC_ENABLE 0x00000000 /* ECC enable register */
+#define ECC_FSTATUS 0x00000008 /* ECC fault status register */
+#define ECC_FADDR 0x00000010 /* ECC fault address register */
+#define ECC_DIGNOSTIC 0x00000018 /* ECC diagnostics register */
+#define ECC_MBAENAB 0x00000020 /* MBus arbiter enable register */
+#define ECC_DMESG 0x00001000 /* Diagnostic message passing area */
+
+/* ECC MBus Arbiter Enable register:
+ *
+ * ----------------------------------------
+ * | |SBUS|MOD3|MOD2|MOD1|RSV|
+ * ----------------------------------------
+ * 31 5 4 3 2 1 0
+ *
+ * SBUS: Enable MBus Arbiter on the SBus 0=off 1=on
+ * MOD3: Enable MBus Arbiter on MBus module 3 0=off 1=on
+ * MOD2: Enable MBus Arbiter on MBus module 2 0=off 1=on
+ * MOD1: Enable MBus Arbiter on MBus module 1 0=off 1=on
+ */
+
+#define ECC_MBAE_SBUS 0x00000010
+#define ECC_MBAE_MOD3 0x00000008
+#define ECC_MBAE_MOD2 0x00000004
+#define ECC_MBAE_MOD1 0x00000002
+
+/* ECC Fault Control Register layout:
+ *
+ * -----------------------------
+ * | RESV | ECHECK | EINT |
+ * -----------------------------
+ * 31 2 1 0
+ *
+ * ECHECK: Enable ECC checking. 0=off 1=on
+ * EINT: Enable Interrupts for correctable errors. 0=off 1=on
+ */
+#define ECC_FCR_CHECK 0x00000002
+#define ECC_FCR_INTENAB 0x00000001
+
+/* ECC Fault Address Register Zero layout:
+ *
+ * -----------------------------------------------------
+ * | MID | S | RSV | VA | BM |AT| C| SZ |TYP| PADDR |
+ * -----------------------------------------------------
+ * 31-28 27 26-22 21-14 13 12 11 10-8 7-4 3-0
+ *
+ * MID: ModuleID of the faulting processor. ie. who did it?
+ * S: Supervisor/Privileged access? 0=no 1=yes
+ * VA: Bits 19-12 of the virtual faulting address, these are the
+ * superset bits in the virtual cache and can be used for
+ * a flush operation if necessary.
+ * BM: Boot mode? 0=no 1=yes This is just like the SRMMU boot
+ * mode bit.
+ * AT: Did this fault happen during an atomic instruction? 0=no
+ * 1=yes. This means either an 'ldstub' or 'swap' instruction
+ * was in progress (but not finished) when this fault happened.
+ * This indicated whether the bus was locked when the fault
+ * occurred.
+ * C: Did the pte for this access indicate that it was cacheable?
+ * 0=no 1=yes
+ * SZ: The size of the transaction.
+ * TYP: The transaction type.
+ * PADDR: Bits 35-32 of the physical address for the fault.
+ */
+#define ECC_FADDR0_MIDMASK 0xf0000000
+#define ECC_FADDR0_S 0x08000000
+#define ECC_FADDR0_VADDR 0x003fc000
+#define ECC_FADDR0_BMODE 0x00002000
+#define ECC_FADDR0_ATOMIC 0x00001000
+#define ECC_FADDR0_CACHE 0x00000800
+#define ECC_FADDR0_SIZE 0x00000700
+#define ECC_FADDR0_TYPE 0x000000f0
+#define ECC_FADDR0_PADDR 0x0000000f
+
+/* ECC Fault Address Register One layout:
+ *
+ * -------------------------------------
+ * | Physical Address 31-0 |
+ * -------------------------------------
+ * 31 0
+ *
+ * You get the upper 4 bits of the physical address from the
+ * PADDR field in ECC Fault Address Zero register.
+ */
+
+/* ECC Fault Status Register layout:
+ *
+ * ----------------------------------------------
+ * | RESV|C2E|MULT|SYNDROME|DWORD|UNC|TIMEO|BS|C|
+ * ----------------------------------------------
+ * 31-18 17 16 15-8 7-4 3 2 1 0
+ *
+ * C2E: A C2 graphics error occurred. 0=no 1=yes (SS10 only)
+ * MULT: Multiple errors occurred ;-O 0=no 1=prom_panic(yes)
+ * SYNDROME: Controller is mentally unstable.
+ * DWORD:
+ * UNC: Uncorrectable error. 0=no 1=yes
+ * TIMEO: Timeout occurred. 0=no 1=yes
+ * BS: C2 graphics bad slot access. 0=no 1=yes (SS10 only)
+ * C: Correctable error? 0=no 1=yes
+ */
+
+#define ECC_FSR_C2ERR 0x00020000
+#define ECC_FSR_MULT 0x00010000
+#define ECC_FSR_SYND 0x0000ff00
+#define ECC_FSR_DWORD 0x000000f0
+#define ECC_FSR_UNC 0x00000008
+#define ECC_FSR_TIMEO 0x00000004
+#define ECC_FSR_BADSLOT 0x00000002
+#define ECC_FSR_C 0x00000001
+
+#endif /* !(_SPARC_ECC_H) */
diff --git a/arch/sparc/include/asm/eeprom.h b/arch/sparc/include/asm/eeprom.h
new file mode 100644
index 000000000..e17beeceb
--- /dev/null
+++ b/arch/sparc/include/asm/eeprom.h
@@ -0,0 +1,9 @@
+/*
+ * eeprom.h: Definitions for the Sun eeprom.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* The EEPROM and the Mostek Mk48t02 use the same IO address space
+ * for their registers/data areas. The IDPROM lives here too.
+ */
diff --git a/arch/sparc/include/asm/elf.h b/arch/sparc/include/asm/elf.h
new file mode 100644
index 000000000..bbfb4b002
--- /dev/null
+++ b/arch/sparc/include/asm/elf.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_ELF_H
+#define ___ASM_SPARC_ELF_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/elf_64.h>
+#else
+#include <asm/elf_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h
new file mode 100644
index 000000000..37a6016c9
--- /dev/null
+++ b/arch/sparc/include/asm/elf_32.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASMSPARC_ELF_H
+#define __ASMSPARC_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+/*
+ * Sparc section types
+ */
+#define STT_REGISTER 13
+
+/*
+ * Sparc ELF relocation types
+ */
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+
+/* Bits present in AT_HWCAP, primarily for Sparc32. */
+
+#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */
+#define HWCAP_SPARC_STBAR 2
+#define HWCAP_SPARC_SWAP 4
+#define HWCAP_SPARC_MULDIV 8
+#define HWCAP_SPARC_V9 16
+#define HWCAP_SPARC_ULTRA3 32
+
+#define CORE_DUMP_USE_REGSET
+
+/* Format is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * PSR, PC, nPC, Y, WIM, TBR
+ */
+typedef unsigned long elf_greg_t;
+#define ELF_NGREG 38
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct {
+ union {
+ unsigned long pr_regs[32];
+ double pr_dregs[16];
+ } pr_fr;
+ unsigned long __unused;
+ unsigned long pr_fsr;
+ unsigned char pr_qcnt;
+ unsigned char pr_q_entrysize;
+ unsigned char pr_en;
+ unsigned int pr_q[64];
+} elf_fpregset_t;
+
+#include <asm/mbus.h>
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == EM_SPARC)
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH EM_SPARC
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2MSB
+
+#define ELF_EXEC_PAGESIZE 4096
+
+
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE)
+
+/* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. This can NOT be done in userspace
+ on Sparc. */
+
+/* Most sun4m's have them all. */
+#define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \
+ HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV)
+
+/* This yields a string that ld.so will use to load implementation
+ specific libraries for optimization. This is more specific in
+ intent than poking at uname or /proc/cpuinfo. */
+
+#define ELF_PLATFORM (NULL)
+
+#endif /* !(__ASMSPARC_ELF_H) */
diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h
new file mode 100644
index 000000000..8fb09eec8
--- /dev/null
+++ b/arch/sparc/include/asm/elf_64.h
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_SPARC64_ELF_H
+#define __ASM_SPARC64_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/spitfire.h>
+#include <asm/adi.h>
+
+/*
+ * Sparc section types
+ */
+#define STT_REGISTER 13
+
+/*
+ * Sparc ELF relocation types
+ */
+#define R_SPARC_NONE 0
+#define R_SPARC_8 1
+#define R_SPARC_16 2
+#define R_SPARC_32 3
+#define R_SPARC_DISP8 4
+#define R_SPARC_DISP16 5
+#define R_SPARC_DISP32 6
+#define R_SPARC_WDISP30 7
+#define R_SPARC_WDISP22 8
+#define R_SPARC_HI22 9
+#define R_SPARC_22 10
+#define R_SPARC_13 11
+#define R_SPARC_LO10 12
+#define R_SPARC_GOT10 13
+#define R_SPARC_GOT13 14
+#define R_SPARC_GOT22 15
+#define R_SPARC_PC10 16
+#define R_SPARC_PC22 17
+#define R_SPARC_WPLT30 18
+#define R_SPARC_COPY 19
+#define R_SPARC_GLOB_DAT 20
+#define R_SPARC_JMP_SLOT 21
+#define R_SPARC_RELATIVE 22
+#define R_SPARC_UA32 23
+#define R_SPARC_PLT32 24
+#define R_SPARC_HIPLT22 25
+#define R_SPARC_LOPLT10 26
+#define R_SPARC_PCPLT32 27
+#define R_SPARC_PCPLT22 28
+#define R_SPARC_PCPLT10 29
+#define R_SPARC_10 30
+#define R_SPARC_11 31
+#define R_SPARC_64 32
+#define R_SPARC_OLO10 33
+#define R_SPARC_WDISP16 40
+#define R_SPARC_WDISP19 41
+#define R_SPARC_7 43
+#define R_SPARC_5 44
+#define R_SPARC_6 45
+
+/* Bits present in AT_HWCAP, primarily for Sparc32. */
+#define HWCAP_SPARC_FLUSH 0x00000001
+#define HWCAP_SPARC_STBAR 0x00000002
+#define HWCAP_SPARC_SWAP 0x00000004
+#define HWCAP_SPARC_MULDIV 0x00000008
+#define HWCAP_SPARC_V9 0x00000010
+#define HWCAP_SPARC_ULTRA3 0x00000020
+#define HWCAP_SPARC_BLKINIT 0x00000040
+#define HWCAP_SPARC_N2 0x00000080
+
+/* Solaris compatible AT_HWCAP bits. */
+#define AV_SPARC_MUL32 0x00000100 /* 32x32 multiply is efficient */
+#define AV_SPARC_DIV32 0x00000200 /* 32x32 divide is efficient */
+#define AV_SPARC_FSMULD 0x00000400 /* 'fsmuld' is efficient */
+#define AV_SPARC_V8PLUS 0x00000800 /* v9 insn available to 32bit */
+#define AV_SPARC_POPC 0x00001000 /* 'popc' is efficient */
+#define AV_SPARC_VIS 0x00002000 /* VIS insns available */
+#define AV_SPARC_VIS2 0x00004000 /* VIS2 insns available */
+#define AV_SPARC_ASI_BLK_INIT 0x00008000 /* block init ASIs available */
+#define AV_SPARC_FMAF 0x00010000 /* fused multiply-add */
+#define AV_SPARC_VIS3 0x00020000 /* VIS3 insns available */
+#define AV_SPARC_HPC 0x00040000 /* HPC insns available */
+#define AV_SPARC_RANDOM 0x00080000 /* 'random' insn available */
+#define AV_SPARC_TRANS 0x00100000 /* transaction insns available */
+#define AV_SPARC_FJFMAU 0x00200000 /* unfused multiply-add */
+#define AV_SPARC_IMA 0x00400000 /* integer multiply-add */
+#define AV_SPARC_ASI_CACHE_SPARING \
+ 0x00800000 /* cache sparing ASIs available */
+#define AV_SPARC_PAUSE 0x01000000 /* PAUSE available */
+#define AV_SPARC_CBCOND 0x02000000 /* CBCOND insns available */
+
+/* Solaris decided to enumerate every single crypto instruction type
+ * in the AT_HWCAP bits. This is wasteful, since if crypto is present,
+ * you still need to look in the CFR register to see if the opcode is
+ * really available. So we simply advertise only "crypto" support.
+ */
+#define HWCAP_SPARC_CRYPTO 0x04000000 /* CRYPTO insns available */
+#define HWCAP_SPARC_ADI 0x08000000 /* ADI available */
+
+#define CORE_DUMP_USE_REGSET
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH EM_SPARCV9
+#define ELF_CLASS ELFCLASS64
+#define ELF_DATA ELFDATA2MSB
+
+/* Format of 64-bit elf_gregset_t is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * TSTATE
+ * TPC
+ * TNPC
+ * Y
+ */
+typedef unsigned long elf_greg_t;
+#define ELF_NGREG 36
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct {
+ unsigned long pr_regs[32];
+ unsigned long pr_fsr;
+ unsigned long pr_gsr;
+ unsigned long pr_fprs;
+} elf_fpregset_t;
+
+/* Format of 32-bit elf_gregset_t is:
+ * G0 --> G7
+ * O0 --> O7
+ * L0 --> L7
+ * I0 --> I7
+ * PSR, PC, nPC, Y, WIM, TBR
+ */
+typedef unsigned int compat_elf_greg_t;
+#define COMPAT_ELF_NGREG 38
+typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
+
+typedef struct {
+ union {
+ unsigned int pr_regs[32];
+ unsigned long pr_dregs[16];
+ } pr_fr;
+ unsigned int __unused;
+ unsigned int pr_fsr;
+ unsigned char pr_qcnt;
+ unsigned char pr_q_entrysize;
+ unsigned char pr_en;
+ unsigned int pr_q[64];
+} compat_elf_fpregset_t;
+
+/* UltraSparc extensions. Still unused, but will be eventually. */
+typedef struct {
+ unsigned int pr_type;
+ unsigned int pr_align;
+ union {
+ struct {
+ union {
+ unsigned int pr_regs[32];
+ unsigned long pr_dregs[16];
+ long double pr_qregs[8];
+ } pr_xfr;
+ } pr_v8p;
+ unsigned int pr_xfsr;
+ unsigned int pr_fprs;
+ unsigned int pr_xg[8];
+ unsigned int pr_xo[8];
+ unsigned long pr_tstate;
+ unsigned int pr_filler[8];
+ } pr_un;
+} elf_xregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
+#define compat_elf_check_arch(x) ((x)->e_machine == EM_SPARC || \
+ (x)->e_machine == EM_SPARC32PLUS)
+#define compat_start_thread start_thread32
+
+#define ELF_EXEC_PAGESIZE PAGE_SIZE
+
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+#define ELF_ET_DYN_BASE 0x0000010000000000UL
+#define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL
+
+extern unsigned long sparc64_elf_hwcap;
+#define ELF_HWCAP sparc64_elf_hwcap
+
+/* This yields a string that ld.so will use to load implementation
+ specific libraries for optimization. This is more specific in
+ intent than poking at uname or /proc/cpuinfo. */
+
+#define ELF_PLATFORM (NULL)
+
+#define SET_PERSONALITY(ex) \
+do { if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
+ set_thread_flag(TIF_32BIT); \
+ else \
+ clear_thread_flag(TIF_32BIT); \
+ /* flush_thread will update pgd cache */ \
+ if (personality(current->personality) != PER_LINUX32) \
+ set_personality(PER_LINUX | \
+ (current->personality & (~PER_MASK))); \
+} while (0)
+
+extern unsigned int vdso_enabled;
+
+#define ARCH_DLINFO \
+do { \
+ extern struct adi_config adi_state; \
+ if (vdso_enabled) \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, \
+ (unsigned long)current->mm->context.vdso); \
+ NEW_AUX_ENT(AT_ADI_BLKSZ, adi_state.caps.blksz); \
+ NEW_AUX_ENT(AT_ADI_NBITS, adi_state.caps.nbits); \
+ NEW_AUX_ENT(AT_ADI_UEONADI, adi_state.caps.ue_on_adi); \
+} while (0)
+
+struct linux_binprm;
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+ int uses_interp);
+#endif /* !(__ASM_SPARC64_ELF_H) */
diff --git a/arch/sparc/include/asm/estate.h b/arch/sparc/include/asm/estate.h
new file mode 100644
index 000000000..e5e0f84ac
--- /dev/null
+++ b/arch/sparc/include/asm/estate.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_ESTATE_H
+#define _SPARC64_ESTATE_H
+
+/* UltraSPARC-III E-cache Error Enable */
+#define ESTATE_ERROR_FMT 0x0000000000040000 /* Force MTAG ECC */
+#define ESTATE_ERROR_FMESS 0x000000000003c000 /* Forced MTAG ECC val */
+#define ESTATE_ERROR_FMD 0x0000000000002000 /* Force DATA ECC */
+#define ESTATE_ERROR_FDECC 0x0000000000001ff0 /* Forced DATA ECC val */
+#define ESTATE_ERROR_UCEEN 0x0000000000000008 /* See below */
+#define ESTATE_ERROR_NCEEN 0x0000000000000002 /* See below */
+#define ESTATE_ERROR_CEEN 0x0000000000000001 /* See below */
+
+/* UCEEN enables the fast_ECC_error trap for: 1) software correctable E-cache
+ * errors 2) uncorrectable E-cache errors. Such events only occur on reads
+ * of the E-cache by the local processor for: 1) data loads 2) instruction
+ * fetches 3) atomic operations. Such events _cannot_ occur for: 1) merge
+ * 2) writeback 2) copyout. The AFSR bits associated with these traps are
+ * UCC and UCU.
+ */
+
+/* NCEEN enables instruction_access_error, data_access_error, and ECC_error traps
+ * for uncorrectable ECC errors and system errors.
+ *
+ * Uncorrectable system bus data error or MTAG ECC error, system bus TimeOUT,
+ * or system bus BusERR:
+ * 1) As the result of an instruction fetch, will generate instruction_access_error
+ * 2) As the result of a load etc. will generate data_access_error.
+ * 3) As the result of store merge completion, writeback, or copyout will
+ * generate a disrupting ECC_error trap.
+ * 4) As the result of such errors on instruction vector fetch can generate any
+ * of the 3 trap types.
+ *
+ * The AFSR bits associated with these traps are EMU, EDU, WDU, CPU, IVU, UE,
+ * BERR, and TO.
+ */
+
+/* CEEN enables the ECC_error trap for hardware corrected ECC errors. System bus
+ * reads resulting in a hardware corrected data or MTAG ECC error will generate an
+ * ECC_error disrupting trap with this bit enabled.
+ *
+ * This same trap will also be generated when a hardware corrected ECC error results
+ * during store merge, writeback, and copyout operations.
+ */
+
+/* In general, if the trap enable bits above are disabled the AFSR bits will still
+ * log the events even though the trap will not be generated by the processor.
+ */
+
+#endif /* _SPARC64_ESTATE_H */
diff --git a/arch/sparc/include/asm/extable.h b/arch/sparc/include/asm/extable.h
new file mode 100644
index 000000000..554a9dc37
--- /dev/null
+++ b/arch/sparc/include/asm/extable.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_EXTABLE_H
+#define __ASM_EXTABLE_H
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue. No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path. This means when everything is well,
+ * we don't even have to jump over them. Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry {
+ unsigned int insn, fixup;
+};
+
+#endif
diff --git a/arch/sparc/include/asm/fb.h b/arch/sparc/include/asm/fb.h
new file mode 100644
index 000000000..572ecd3e1
--- /dev/null
+++ b/arch/sparc/include/asm/fb.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_FB_H_
+#define _SPARC_FB_H_
+
+#include <linux/io.h>
+
+struct fb_info;
+struct file;
+struct vm_area_struct;
+
+#ifdef CONFIG_SPARC32
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+ unsigned long off)
+{ }
+#define fb_pgprotect fb_pgprotect
+#endif
+
+int fb_is_primary_device(struct fb_info *info);
+#define fb_is_primary_device fb_is_primary_device
+
+static inline void fb_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
+{
+ sbus_memcpy_fromio(to, from, n);
+}
+#define fb_memcpy_fromio fb_memcpy_fromio
+
+static inline void fb_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
+{
+ sbus_memcpy_toio(to, from, n);
+}
+#define fb_memcpy_toio fb_memcpy_toio
+
+static inline void fb_memset_io(volatile void __iomem *addr, int c, size_t n)
+{
+ sbus_memset_io(addr, c, n);
+}
+#define fb_memset fb_memset_io
+
+#include <asm-generic/fb.h>
+
+#endif /* _SPARC_FB_H_ */
diff --git a/arch/sparc/include/asm/fbio.h b/arch/sparc/include/asm/fbio.h
new file mode 100644
index 000000000..02654cb95
--- /dev/null
+++ b/arch/sparc/include/asm/fbio.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_FBIO_H
+#define __LINUX_FBIO_H
+
+#include <uapi/asm/fbio.h>
+
+#define FBIOPUTCMAP_SPARC _IOW('F', 3, struct fbcmap)
+#define FBIOGETCMAP_SPARC _IOW('F', 4, struct fbcmap)
+/* Addresses on the fd of a cgsix that are mappable */
+#define CG6_FBC 0x70000000
+#define CG6_TEC 0x70001000
+#define CG6_BTREGS 0x70002000
+#define CG6_FHC 0x70004000
+#define CG6_THC 0x70005000
+#define CG6_ROM 0x70006000
+#define CG6_RAM 0x70016000
+#define CG6_DHC 0x80000000
+
+#define CG3_MMAP_OFFSET 0x4000000
+
+/* Addresses on the fd of a tcx that are mappable */
+#define TCX_RAM8BIT 0x00000000
+#define TCX_RAM24BIT 0x01000000
+#define TCX_UNK3 0x10000000
+#define TCX_UNK4 0x20000000
+#define TCX_CONTROLPLANE 0x28000000
+#define TCX_UNK6 0x30000000
+#define TCX_UNK7 0x38000000
+#define TCX_TEC 0x70000000
+#define TCX_BTREGS 0x70002000
+#define TCX_THC 0x70004000
+#define TCX_DHC 0x70008000
+#define TCX_ALT 0x7000a000
+#define TCX_SYNC 0x7000e000
+#define TCX_UNK2 0x70010000
+
+/* CG14 definitions */
+
+/* Offsets into the OBIO space: */
+#define CG14_REGS 0 /* registers */
+#define CG14_CURSORREGS 0x1000 /* cursor registers */
+#define CG14_DACREGS 0x2000 /* DAC registers */
+#define CG14_XLUT 0x3000 /* X Look Up Table -- ??? */
+#define CG14_CLUT1 0x4000 /* Color Look Up Table */
+#define CG14_CLUT2 0x5000 /* Color Look Up Table */
+#define CG14_CLUT3 0x6000 /* Color Look Up Table */
+#define CG14_AUTO 0xf000
+
+struct fbcmap32 {
+ int index; /* first element (0 origin) */
+ int count;
+ u32 red;
+ u32 green;
+ u32 blue;
+};
+
+#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
+#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
+
+struct fbcursor32 {
+ short set; /* what to set, choose from the list above */
+ short enable; /* cursor on/off */
+ struct fbcurpos pos; /* cursor position */
+ struct fbcurpos hot; /* cursor hot spot */
+ struct fbcmap32 cmap; /* color map info */
+ struct fbcurpos size; /* cursor bit map size */
+ u32 image; /* cursor image bits */
+ u32 mask; /* cursor mask bits */
+};
+
+#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
+#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
+#endif /* __LINUX_FBIO_H */
diff --git a/arch/sparc/include/asm/fhc.h b/arch/sparc/include/asm/fhc.h
new file mode 100644
index 000000000..0627fa126
--- /dev/null
+++ b/arch/sparc/include/asm/fhc.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* fhc.h: FHC and Clock board register definitions.
+ *
+ * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _SPARC64_FHC_H
+#define _SPARC64_FHC_H
+
+/* Clock board register offsets. */
+#define CLOCK_CTRL 0x00UL /* Main control */
+#define CLOCK_STAT1 0x10UL /* Status one */
+#define CLOCK_STAT2 0x20UL /* Status two */
+#define CLOCK_PWRSTAT 0x30UL /* Power status */
+#define CLOCK_PWRPRES 0x40UL /* Power presence */
+#define CLOCK_TEMP 0x50UL /* Temperature */
+#define CLOCK_IRQDIAG 0x60UL /* IRQ diagnostics */
+#define CLOCK_PWRSTAT2 0x70UL /* Power status two */
+
+#define CLOCK_CTRL_LLED 0x04 /* Left LED, 0 == on */
+#define CLOCK_CTRL_MLED 0x02 /* Mid LED, 1 == on */
+#define CLOCK_CTRL_RLED 0x01 /* RIght LED, 1 == on */
+
+/* Firehose controller register offsets */
+#define FHC_PREGS_ID 0x00UL /* FHC ID */
+#define FHC_ID_VERS 0xf0000000 /* Version of this FHC */
+#define FHC_ID_PARTID 0x0ffff000 /* Part ID code (0x0f9f == FHC) */
+#define FHC_ID_MANUF 0x0000007e /* Manufacturer (0x3e == SUN's JEDEC)*/
+#define FHC_ID_RESV 0x00000001 /* Read as one */
+#define FHC_PREGS_RCS 0x10UL /* FHC Reset Control/Status Register */
+#define FHC_RCS_POR 0x80000000 /* Last reset was a power cycle */
+#define FHC_RCS_SPOR 0x40000000 /* Last reset was sw power on reset */
+#define FHC_RCS_SXIR 0x20000000 /* Last reset was sw XIR reset */
+#define FHC_RCS_BPOR 0x10000000 /* Last reset was due to POR button */
+#define FHC_RCS_BXIR 0x08000000 /* Last reset was due to XIR button */
+#define FHC_RCS_WEVENT 0x04000000 /* CPU reset was due to wakeup event */
+#define FHC_RCS_CFATAL 0x02000000 /* Centerplane Fatal Error signalled */
+#define FHC_RCS_FENAB 0x01000000 /* Fatal errors elicit system reset */
+#define FHC_PREGS_CTRL 0x20UL /* FHC Control Register */
+#define FHC_CONTROL_ICS 0x00100000 /* Ignore Centerplane Signals */
+#define FHC_CONTROL_FRST 0x00080000 /* Fatal Error Reset Enable */
+#define FHC_CONTROL_LFAT 0x00040000 /* AC/DC signalled a local error */
+#define FHC_CONTROL_SLINE 0x00010000 /* Firmware Synchronization Line */
+#define FHC_CONTROL_DCD 0x00008000 /* DC-->DC Converter Disable */
+#define FHC_CONTROL_POFF 0x00004000 /* AC/DC Controller PLL Disable */
+#define FHC_CONTROL_FOFF 0x00002000 /* FHC Controller PLL Disable */
+#define FHC_CONTROL_AOFF 0x00001000 /* CPU A SRAM/SBD Low Power Mode */
+#define FHC_CONTROL_BOFF 0x00000800 /* CPU B SRAM/SBD Low Power Mode */
+#define FHC_CONTROL_PSOFF 0x00000400 /* Turns off this FHC's power supply */
+#define FHC_CONTROL_IXIST 0x00000200 /* 0=FHC tells clock board it exists */
+#define FHC_CONTROL_XMSTR 0x00000100 /* 1=Causes this FHC to be XIR master*/
+#define FHC_CONTROL_LLED 0x00000040 /* 0=Left LED ON */
+#define FHC_CONTROL_MLED 0x00000020 /* 1=Middle LED ON */
+#define FHC_CONTROL_RLED 0x00000010 /* 1=Right LED */
+#define FHC_CONTROL_BPINS 0x00000003 /* Spare Bidirectional Pins */
+#define FHC_PREGS_BSR 0x30UL /* FHC Board Status Register */
+#define FHC_BSR_DA64 0x00040000 /* Port A: 0=128bit 1=64bit data path */
+#define FHC_BSR_DB64 0x00020000 /* Port B: 0=128bit 1=64bit data path */
+#define FHC_BSR_BID 0x0001e000 /* Board ID */
+#define FHC_BSR_SA 0x00001c00 /* Port A UPA Speed (from the pins) */
+#define FHC_BSR_SB 0x00000380 /* Port B UPA Speed (from the pins) */
+#define FHC_BSR_NDIAG 0x00000040 /* Not in Diag Mode */
+#define FHC_BSR_NTBED 0x00000020 /* Not in TestBED Mode */
+#define FHC_BSR_NIA 0x0000001c /* Jumper, bit 18 in PROM space */
+#define FHC_BSR_SI 0x00000001 /* Spare input pin value */
+#define FHC_PREGS_ECC 0x40UL /* FHC ECC Control Register (16 bits) */
+#define FHC_PREGS_JCTRL 0xf0UL /* FHC JTAG Control Register */
+#define FHC_JTAG_CTRL_MENAB 0x80000000 /* Indicates this is JTAG Master */
+#define FHC_JTAG_CTRL_MNONE 0x40000000 /* Indicates no JTAG Master present */
+#define FHC_PREGS_JCMD 0x100UL /* FHC JTAG Command Register */
+#define FHC_IREG_IGN 0x00UL /* This FHC's IGN */
+#define FHC_FFREGS_IMAP 0x00UL /* FHC Fanfail IMAP */
+#define FHC_FFREGS_ICLR 0x10UL /* FHC Fanfail ICLR */
+#define FHC_SREGS_IMAP 0x00UL /* FHC System IMAP */
+#define FHC_SREGS_ICLR 0x10UL /* FHC System ICLR */
+#define FHC_UREGS_IMAP 0x00UL /* FHC Uart IMAP */
+#define FHC_UREGS_ICLR 0x10UL /* FHC Uart ICLR */
+#define FHC_TREGS_IMAP 0x00UL /* FHC TOD IMAP */
+#define FHC_TREGS_ICLR 0x10UL /* FHC TOD ICLR */
+
+#endif /* !(_SPARC64_FHC_H) */
diff --git a/arch/sparc/include/asm/floppy.h b/arch/sparc/include/asm/floppy.h
new file mode 100644
index 000000000..4b315802e
--- /dev/null
+++ b/arch/sparc/include/asm/floppy.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_FLOPPY_H
+#define ___ASM_SPARC_FLOPPY_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/floppy_64.h>
+#else
+#include <asm/floppy_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h
new file mode 100644
index 000000000..836f6575a
--- /dev/null
+++ b/arch/sparc/include/asm/floppy_32.h
@@ -0,0 +1,393 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* asm/floppy.h: Sparc specific parts of the Floppy driver.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef __ASM_SPARC_FLOPPY_H
+#define __ASM_SPARC_FLOPPY_H
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pgtable.h>
+
+#include <asm/idprom.h>
+#include <asm/oplib.h>
+#include <asm/auxio.h>
+#include <asm/setup.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+
+/* We don't need no stinkin' I/O port allocation crap. */
+#undef release_region
+#undef request_region
+#define release_region(X, Y) do { } while(0)
+#define request_region(X, Y, Z) (1)
+
+/* References:
+ * 1) Netbsd Sun floppy driver.
+ * 2) NCR 82077 controller manual
+ * 3) Intel 82077 controller manual
+ */
+struct sun_flpy_controller {
+ volatile unsigned char status_82072; /* Main Status reg. */
+#define dcr_82072 status_82072 /* Digital Control reg. */
+#define status1_82077 status_82072 /* Auxiliary Status reg. 1 */
+
+ volatile unsigned char data_82072; /* Data fifo. */
+#define status2_82077 data_82072 /* Auxiliary Status reg. 2 */
+
+ volatile unsigned char dor_82077; /* Digital Output reg. */
+ volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
+
+ volatile unsigned char status_82077; /* Main Status Register. */
+#define drs_82077 status_82077 /* Digital Rate Select reg. */
+
+ volatile unsigned char data_82077; /* Data fifo. */
+ volatile unsigned char ___unused;
+ volatile unsigned char dir_82077; /* Digital Input reg. */
+#define dcr_82077 dir_82077 /* Config Control reg. */
+};
+
+/* You'll only ever find one controller on a SparcStation anyways. */
+static struct sun_flpy_controller *sun_fdc = NULL;
+
+struct sun_floppy_ops {
+ unsigned char (*fd_inb)(int port);
+ void (*fd_outb)(unsigned char value, int port);
+};
+
+static struct sun_floppy_ops sun_fdops;
+
+#define fd_inb(base, reg) sun_fdops.fd_inb(reg)
+#define fd_outb(value, base, reg) sun_fdops.fd_outb(value, reg)
+#define fd_enable_dma() sun_fd_enable_dma()
+#define fd_disable_dma() sun_fd_disable_dma()
+#define fd_request_dma() (0) /* nothing... */
+#define fd_free_dma() /* nothing... */
+#define fd_clear_dma_ff() /* nothing... */
+#define fd_set_dma_mode(mode) sun_fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr) sun_fd_set_dma_addr(addr)
+#define fd_set_dma_count(count) sun_fd_set_dma_count(count)
+#define fd_enable_irq() /* nothing... */
+#define fd_disable_irq() /* nothing... */
+#define fd_request_irq() sun_fd_request_irq()
+#define fd_free_irq() /* nothing... */
+#if 0 /* P3: added by Alain, these cause a MMU corruption. 19960524 XXX */
+#define fd_dma_mem_alloc(size) ((unsigned long) vmalloc(size))
+#define fd_dma_mem_free(addr,size) (vfree((void *)(addr)))
+#endif
+
+/* XXX This isn't really correct. XXX */
+#define get_dma_residue(x) (0)
+
+#define FLOPPY0_TYPE 4
+#define FLOPPY1_TYPE 0
+
+/* Super paranoid... */
+#undef HAVE_DISABLE_HLT
+
+/* Here is where we catch the floppy driver trying to initialize,
+ * therefore this is where we call the PROM device tree probing
+ * routine etc. on the Sparc.
+ */
+#define FDC1 sun_floppy_init()
+
+#define N_FDC 1
+#define N_DRIVE 8
+
+/* No 64k boundary crossing problems on the Sparc. */
+#define CROSS_64KB(a,s) (0)
+
+/* Routines unique to each controller type on a Sun. */
+static void sun_set_dor(unsigned char value, int fdc_82077)
+{
+ if (fdc_82077)
+ sun_fdc->dor_82077 = value;
+}
+
+static unsigned char sun_read_dir(void)
+{
+ return sun_fdc->dir_82077;
+}
+
+static unsigned char sun_82072_fd_inb(int port)
+{
+ udelay(5);
+ switch (port) {
+ default:
+ printk("floppy: Asked to read unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case FD_STATUS:
+ return sun_fdc->status_82072 & ~STATUS_DMA;
+ case FD_DATA:
+ return sun_fdc->data_82072;
+ case FD_DIR:
+ return sun_read_dir();
+ }
+ panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun_82072_fd_outb(unsigned char value, int port)
+{
+ udelay(5);
+ switch (port) {
+ default:
+ printk("floppy: Asked to write to unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case FD_DOR:
+ sun_set_dor(value, 0);
+ break;
+ case FD_DATA:
+ sun_fdc->data_82072 = value;
+ break;
+ case FD_DCR:
+ sun_fdc->dcr_82072 = value;
+ break;
+ case FD_DSR:
+ sun_fdc->status_82072 = value;
+ break;
+ }
+ return;
+}
+
+static unsigned char sun_82077_fd_inb(int port)
+{
+ udelay(5);
+ switch (port) {
+ default:
+ printk("floppy: Asked to read unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case FD_SRA:
+ return sun_fdc->status1_82077;
+ case FD_SRB:
+ return sun_fdc->status2_82077;
+ case FD_DOR:
+ return sun_fdc->dor_82077;
+ case FD_TDR:
+ return sun_fdc->tapectl_82077;
+ case FD_STATUS:
+ return sun_fdc->status_82077 & ~STATUS_DMA;
+ case FD_DATA:
+ return sun_fdc->data_82077;
+ case FD_DIR:
+ return sun_read_dir();
+ }
+ panic("sun_82077_fd_inb: How did I get here?");
+}
+
+static void sun_82077_fd_outb(unsigned char value, int port)
+{
+ udelay(5);
+ switch (port) {
+ default:
+ printk("floppy: Asked to write to unknown port %d\n", port);
+ panic("floppy: Port bolixed.");
+ case FD_DOR:
+ sun_set_dor(value, 1);
+ break;
+ case FD_DATA:
+ sun_fdc->data_82077 = value;
+ break;
+ case FD_DCR:
+ sun_fdc->dcr_82077 = value;
+ break;
+ case FD_DSR:
+ sun_fdc->status_82077 = value;
+ break;
+ case FD_TDR:
+ sun_fdc->tapectl_82077 = value;
+ break;
+ }
+ return;
+}
+
+/* For pseudo-dma (Sun floppy drives have no real DMA available to
+ * them so we must eat the data fifo bytes directly ourselves) we have
+ * three state variables. doing_pdma tells our inline low-level
+ * assembly floppy interrupt entry point whether it should sit and eat
+ * bytes from the fifo or just transfer control up to the higher level
+ * floppy interrupt c-code. I tried very hard but I could not get the
+ * pseudo-dma to work in c-code without getting many overruns and
+ * underruns. If non-zero, doing_pdma encodes the direction of
+ * the transfer for debugging. 1=read 2=write
+ */
+
+/* Common routines to all controller types on the Sparc. */
+static inline void virtual_dma_init(void)
+{
+ /* nothing... */
+}
+
+static inline void sun_fd_disable_dma(void)
+{
+ doing_pdma = 0;
+ pdma_base = NULL;
+}
+
+static inline void sun_fd_set_dma_mode(int mode)
+{
+ switch(mode) {
+ case DMA_MODE_READ:
+ doing_pdma = 1;
+ break;
+ case DMA_MODE_WRITE:
+ doing_pdma = 2;
+ break;
+ default:
+ printk("Unknown dma mode %d\n", mode);
+ panic("floppy: Giving up...");
+ }
+}
+
+static inline void sun_fd_set_dma_addr(char *buffer)
+{
+ pdma_vaddr = buffer;
+}
+
+static inline void sun_fd_set_dma_count(int length)
+{
+ pdma_size = length;
+}
+
+static inline void sun_fd_enable_dma(void)
+{
+ pdma_base = pdma_vaddr;
+ pdma_areasize = pdma_size;
+}
+
+int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler);
+
+static int sun_fd_request_irq(void)
+{
+ static int once = 0;
+
+ if (!once) {
+ once = 1;
+ return sparc_floppy_request_irq(FLOPPY_IRQ, floppy_interrupt);
+ } else {
+ return 0;
+ }
+}
+
+static struct linux_prom_registers fd_regs[2];
+
+static int sun_floppy_init(void)
+{
+ struct platform_device *op;
+ struct device_node *dp;
+ struct resource r;
+ char state[128];
+ phandle fd_node;
+ phandle tnode;
+ int num_regs;
+
+ use_virtual_dma = 1;
+
+ /* Forget it if we aren't on a machine that could possibly
+ * ever have a floppy drive.
+ */
+ if (sparc_cpu_model != sun4m) {
+ /* We certainly don't have a floppy controller. */
+ goto no_sun_fdc;
+ }
+ /* Well, try to find one. */
+ tnode = prom_getchild(prom_root_node);
+ fd_node = prom_searchsiblings(tnode, "obio");
+ if (fd_node != 0) {
+ tnode = prom_getchild(fd_node);
+ fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
+ } else {
+ fd_node = prom_searchsiblings(tnode, "fd");
+ }
+ if (fd_node == 0) {
+ goto no_sun_fdc;
+ }
+
+ /* The sun4m lets us know if the controller is actually usable. */
+ if (prom_getproperty(fd_node, "status", state, sizeof(state)) != -1) {
+ if(!strcmp(state, "disabled")) {
+ goto no_sun_fdc;
+ }
+ }
+ num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
+ num_regs = (num_regs / sizeof(fd_regs[0]));
+ prom_apply_obio_ranges(fd_regs, num_regs);
+ memset(&r, 0, sizeof(r));
+ r.flags = fd_regs[0].which_io;
+ r.start = fd_regs[0].phys_addr;
+ sun_fdc = of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
+
+ /* Look up irq in platform_device.
+ * We try "SUNW,fdtwo" and "fd"
+ */
+ op = NULL;
+ for_each_node_by_name(dp, "SUNW,fdtwo") {
+ op = of_find_device_by_node(dp);
+ if (op)
+ break;
+ }
+ if (!op) {
+ for_each_node_by_name(dp, "fd") {
+ op = of_find_device_by_node(dp);
+ if (op)
+ break;
+ }
+ }
+ if (!op)
+ goto no_sun_fdc;
+
+ FLOPPY_IRQ = op->archdata.irqs[0];
+
+ /* Last minute sanity check... */
+ if (sun_fdc->status_82072 == 0xff) {
+ sun_fdc = NULL;
+ goto no_sun_fdc;
+ }
+
+ sun_fdops.fd_inb = sun_82077_fd_inb;
+ sun_fdops.fd_outb = sun_82077_fd_outb;
+ fdc_status = &sun_fdc->status_82077;
+
+ if (sun_fdc->dor_82077 == 0x80) {
+ sun_fdc->dor_82077 = 0x02;
+ if (sun_fdc->dor_82077 == 0x80) {
+ sun_fdops.fd_inb = sun_82072_fd_inb;
+ sun_fdops.fd_outb = sun_82072_fd_outb;
+ fdc_status = &sun_fdc->status_82072;
+ }
+ }
+
+ /* Success... */
+ allowed_drive_mask = 0x01;
+ return (int) sun_fdc;
+
+no_sun_fdc:
+ return -1;
+}
+
+static int sparc_eject(void)
+{
+ set_dor(0x00, 0xff, 0x90);
+ udelay(500);
+ set_dor(0x00, 0x6f, 0x00);
+ udelay(500);
+ return 0;
+}
+
+#define fd_eject(drive) sparc_eject()
+
+#define EXTRA_FLOPPY_PARAMS
+
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({ unsigned long flags; \
+ spin_lock_irqsave(&dma_spin_lock, flags); \
+ flags; \
+})
+
+#define release_dma_lock(__flags) \
+ spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
+#endif /* !(__ASM_SPARC_FLOPPY_H) */
diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h
new file mode 100644
index 000000000..6efeb24b0
--- /dev/null
+++ b/arch/sparc/include/asm/floppy_64.h
@@ -0,0 +1,779 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* floppy.h: Sparc specific parts of the Floppy driver.
+ *
+ * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * Ultra/PCI support added: Sep 1997 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef __ASM_SPARC64_FLOPPY_H
+#define __ASM_SPARC64_FLOPPY_H
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/auxio.h>
+
+/*
+ * Define this to enable exchanging drive 0 and 1 if only drive 1 is
+ * probed on PCI machines.
+ */
+#undef PCI_FDC_SWAP_DRIVES
+
+
+/* References:
+ * 1) Netbsd Sun floppy driver.
+ * 2) NCR 82077 controller manual
+ * 3) Intel 82077 controller manual
+ */
+struct sun_flpy_controller {
+ volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
+ volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
+ volatile unsigned char dor_82077; /* Digital Output reg. */
+ volatile unsigned char tapectl_82077; /* Tape Control reg */
+ volatile unsigned char status_82077; /* Main Status Register. */
+#define drs_82077 status_82077 /* Digital Rate Select reg. */
+ volatile unsigned char data_82077; /* Data fifo. */
+ volatile unsigned char ___unused;
+ volatile unsigned char dir_82077; /* Digital Input reg. */
+#define dcr_82077 dir_82077 /* Config Control reg. */
+};
+
+/* You'll only ever find one controller on an Ultra anyways. */
+static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
+unsigned long fdc_status;
+static struct platform_device *floppy_op = NULL;
+
+struct sun_floppy_ops {
+ unsigned char (*fd_inb) (unsigned long port, unsigned int reg);
+ void (*fd_outb) (unsigned char value, unsigned long base,
+ unsigned int reg);
+ void (*fd_enable_dma) (void);
+ void (*fd_disable_dma) (void);
+ void (*fd_set_dma_mode) (int);
+ void (*fd_set_dma_addr) (char *);
+ void (*fd_set_dma_count) (int);
+ unsigned int (*get_dma_residue) (void);
+ int (*fd_request_irq) (void);
+ void (*fd_free_irq) (void);
+ int (*fd_eject) (int);
+};
+
+static struct sun_floppy_ops sun_fdops;
+
+#define fd_inb(base, reg) sun_fdops.fd_inb(base, reg)
+#define fd_outb(value, base, reg) sun_fdops.fd_outb(value, base, reg)
+#define fd_enable_dma() sun_fdops.fd_enable_dma()
+#define fd_disable_dma() sun_fdops.fd_disable_dma()
+#define fd_request_dma() (0) /* nothing... */
+#define fd_free_dma() /* nothing... */
+#define fd_clear_dma_ff() /* nothing... */
+#define fd_set_dma_mode(mode) sun_fdops.fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr) sun_fdops.fd_set_dma_addr(addr)
+#define fd_set_dma_count(count) sun_fdops.fd_set_dma_count(count)
+#define get_dma_residue(x) sun_fdops.get_dma_residue()
+#define fd_request_irq() sun_fdops.fd_request_irq()
+#define fd_free_irq() sun_fdops.fd_free_irq()
+#define fd_eject(drive) sun_fdops.fd_eject(drive)
+
+/* Super paranoid... */
+#undef HAVE_DISABLE_HLT
+
+static int sun_floppy_types[2] = { 0, 0 };
+
+/* Here is where we catch the floppy driver trying to initialize,
+ * therefore this is where we call the PROM device tree probing
+ * routine etc. on the Sparc.
+ */
+#define FLOPPY0_TYPE sun_floppy_init()
+#define FLOPPY1_TYPE sun_floppy_types[1]
+
+#define FDC1 ((unsigned long)sun_fdc)
+
+#define N_FDC 1
+#define N_DRIVE 8
+
+/* No 64k boundary crossing problems on the Sparc. */
+#define CROSS_64KB(a,s) (0)
+
+static unsigned char sun_82077_fd_inb(unsigned long base, unsigned int reg)
+{
+ udelay(5);
+ switch (reg) {
+ default:
+ printk("floppy: Asked to read unknown port %x\n", reg);
+ panic("floppy: Port bolixed.");
+ case FD_STATUS:
+ return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA;
+ case FD_DATA:
+ return sbus_readb(&sun_fdc->data_82077);
+ case FD_DIR:
+ /* XXX: Is DCL on 0x80 in sun4m? */
+ return sbus_readb(&sun_fdc->dir_82077);
+ }
+ panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun_82077_fd_outb(unsigned char value, unsigned long base,
+ unsigned int reg)
+{
+ udelay(5);
+ switch (reg) {
+ default:
+ printk("floppy: Asked to write to unknown port %x\n", reg);
+ panic("floppy: Port bolixed.");
+ case FD_DOR:
+ /* Happily, the 82077 has a real DOR register. */
+ sbus_writeb(value, &sun_fdc->dor_82077);
+ break;
+ case FD_DATA:
+ sbus_writeb(value, &sun_fdc->data_82077);
+ break;
+ case FD_DCR:
+ sbus_writeb(value, &sun_fdc->dcr_82077);
+ break;
+ case FD_DSR:
+ sbus_writeb(value, &sun_fdc->status_82077);
+ break;
+ }
+ return;
+}
+
+/* For pseudo-dma (Sun floppy drives have no real DMA available to
+ * them so we must eat the data fifo bytes directly ourselves) we have
+ * three state variables. doing_pdma tells our inline low-level
+ * assembly floppy interrupt entry point whether it should sit and eat
+ * bytes from the fifo or just transfer control up to the higher level
+ * floppy interrupt c-code. I tried very hard but I could not get the
+ * pseudo-dma to work in c-code without getting many overruns and
+ * underruns. If non-zero, doing_pdma encodes the direction of
+ * the transfer for debugging. 1=read 2=write
+ */
+unsigned char *pdma_vaddr;
+unsigned long pdma_size;
+volatile int doing_pdma = 0;
+
+/* This is software state */
+char *pdma_base = NULL;
+unsigned long pdma_areasize;
+
+/* Common routines to all controller types on the Sparc. */
+static void sun_fd_disable_dma(void)
+{
+ doing_pdma = 0;
+ pdma_base = NULL;
+}
+
+static void sun_fd_set_dma_mode(int mode)
+{
+ switch(mode) {
+ case DMA_MODE_READ:
+ doing_pdma = 1;
+ break;
+ case DMA_MODE_WRITE:
+ doing_pdma = 2;
+ break;
+ default:
+ printk("Unknown dma mode %d\n", mode);
+ panic("floppy: Giving up...");
+ }
+}
+
+static void sun_fd_set_dma_addr(char *buffer)
+{
+ pdma_vaddr = buffer;
+}
+
+static void sun_fd_set_dma_count(int length)
+{
+ pdma_size = length;
+}
+
+static void sun_fd_enable_dma(void)
+{
+ pdma_base = pdma_vaddr;
+ pdma_areasize = pdma_size;
+}
+
+irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie)
+{
+ if (likely(doing_pdma)) {
+ void __iomem *stat = (void __iomem *) fdc_status;
+ unsigned char *vaddr = pdma_vaddr;
+ unsigned long size = pdma_size;
+ u8 val;
+
+ while (size) {
+ val = readb(stat);
+ if (unlikely(!(val & 0x80))) {
+ pdma_vaddr = vaddr;
+ pdma_size = size;
+ return IRQ_HANDLED;
+ }
+ if (unlikely(!(val & 0x20))) {
+ pdma_vaddr = vaddr;
+ pdma_size = size;
+ doing_pdma = 0;
+ goto main_interrupt;
+ }
+ if (val & 0x40) {
+ /* read */
+ *vaddr++ = readb(stat + 1);
+ } else {
+ unsigned char data = *vaddr++;
+
+ /* write */
+ writeb(data, stat + 1);
+ }
+ size--;
+ }
+
+ pdma_vaddr = vaddr;
+ pdma_size = size;
+
+ /* Send Terminal Count pulse to floppy controller. */
+ val = readb(auxio_register);
+ val |= AUXIO_AUX1_FTCNT;
+ writeb(val, auxio_register);
+ val &= ~AUXIO_AUX1_FTCNT;
+ writeb(val, auxio_register);
+
+ doing_pdma = 0;
+ }
+
+main_interrupt:
+ return floppy_interrupt(irq, dev_cookie);
+}
+
+static int sun_fd_request_irq(void)
+{
+ static int once = 0;
+ int error;
+
+ if(!once) {
+ once = 1;
+
+ error = request_irq(FLOPPY_IRQ, sparc_floppy_irq,
+ 0, "floppy", NULL);
+
+ return ((error == 0) ? 0 : -1);
+ }
+ return 0;
+}
+
+static void sun_fd_free_irq(void)
+{
+}
+
+static unsigned int sun_get_dma_residue(void)
+{
+ /* XXX This isn't really correct. XXX */
+ return 0;
+}
+
+static int sun_fd_eject(int drive)
+{
+ set_dor(0x00, 0xff, 0x90);
+ udelay(500);
+ set_dor(0x00, 0x6f, 0x00);
+ udelay(500);
+ return 0;
+}
+
+#include <asm/ebus_dma.h>
+#include <asm/ns87303.h>
+
+static struct ebus_dma_info sun_pci_fd_ebus_dma;
+static struct device *sun_floppy_dev;
+static int sun_pci_broken_drive = -1;
+
+struct sun_pci_dma_op {
+ unsigned int addr;
+ int len;
+ int direction;
+ char *buf;
+};
+static struct sun_pci_dma_op sun_pci_dma_current = { -1U, 0, 0, NULL};
+static struct sun_pci_dma_op sun_pci_dma_pending = { -1U, 0, 0, NULL};
+
+irqreturn_t floppy_interrupt(int irq, void *dev_id);
+
+static unsigned char sun_pci_fd_inb(unsigned long base, unsigned int reg)
+{
+ udelay(5);
+ return inb(base + reg);
+}
+
+static void sun_pci_fd_outb(unsigned char val, unsigned long base,
+ unsigned int reg)
+{
+ udelay(5);
+ outb(val, base + reg);
+}
+
+static void sun_pci_fd_broken_outb(unsigned char val, unsigned long base,
+ unsigned int reg)
+{
+ udelay(5);
+ /*
+ * XXX: Due to SUN's broken floppy connector on AX and AXi
+ * we need to turn on MOTOR_0 also, if the floppy is
+ * jumpered to DS1 (like most PC floppies are). I hope
+ * this does not hurt correct hardware like the AXmp.
+ * (Eddie, Sep 12 1998).
+ */
+ if (reg == FD_DOR) {
+ if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
+ val |= 0x10;
+ }
+ }
+ outb(val, base + reg);
+}
+
+#ifdef PCI_FDC_SWAP_DRIVES
+static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long base,
+ unsigned int reg)
+{
+ udelay(5);
+ /*
+ * XXX: Due to SUN's broken floppy connector on AX and AXi
+ * we need to turn on MOTOR_0 also, if the floppy is
+ * jumpered to DS1 (like most PC floppies are). I hope
+ * this does not hurt correct hardware like the AXmp.
+ * (Eddie, Sep 12 1998).
+ */
+ if (reg == FD_DOR) {
+ if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
+ val &= ~(0x03);
+ val |= 0x21;
+ }
+ }
+ outb(val, base + reg);
+}
+#endif /* PCI_FDC_SWAP_DRIVES */
+
+static void sun_pci_fd_enable_dma(void)
+{
+ BUG_ON((NULL == sun_pci_dma_pending.buf) ||
+ (0 == sun_pci_dma_pending.len) ||
+ (0 == sun_pci_dma_pending.direction));
+
+ sun_pci_dma_current.buf = sun_pci_dma_pending.buf;
+ sun_pci_dma_current.len = sun_pci_dma_pending.len;
+ sun_pci_dma_current.direction = sun_pci_dma_pending.direction;
+
+ sun_pci_dma_pending.buf = NULL;
+ sun_pci_dma_pending.len = 0;
+ sun_pci_dma_pending.direction = 0;
+ sun_pci_dma_pending.addr = -1U;
+
+ sun_pci_dma_current.addr =
+ dma_map_single(sun_floppy_dev,
+ sun_pci_dma_current.buf,
+ sun_pci_dma_current.len,
+ sun_pci_dma_current.direction);
+
+ ebus_dma_enable(&sun_pci_fd_ebus_dma, 1);
+
+ if (ebus_dma_request(&sun_pci_fd_ebus_dma,
+ sun_pci_dma_current.addr,
+ sun_pci_dma_current.len))
+ BUG();
+}
+
+static void sun_pci_fd_disable_dma(void)
+{
+ ebus_dma_enable(&sun_pci_fd_ebus_dma, 0);
+ if (sun_pci_dma_current.addr != -1U)
+ dma_unmap_single(sun_floppy_dev,
+ sun_pci_dma_current.addr,
+ sun_pci_dma_current.len,
+ sun_pci_dma_current.direction);
+ sun_pci_dma_current.addr = -1U;
+}
+
+static void sun_pci_fd_set_dma_mode(int mode)
+{
+ if (mode == DMA_MODE_WRITE)
+ sun_pci_dma_pending.direction = DMA_TO_DEVICE;
+ else
+ sun_pci_dma_pending.direction = DMA_FROM_DEVICE;
+
+ ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE);
+}
+
+static void sun_pci_fd_set_dma_count(int length)
+{
+ sun_pci_dma_pending.len = length;
+}
+
+static void sun_pci_fd_set_dma_addr(char *buffer)
+{
+ sun_pci_dma_pending.buf = buffer;
+}
+
+static unsigned int sun_pci_get_dma_residue(void)
+{
+ return ebus_dma_residue(&sun_pci_fd_ebus_dma);
+}
+
+static int sun_pci_fd_request_irq(void)
+{
+ return ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 1);
+}
+
+static void sun_pci_fd_free_irq(void)
+{
+ ebus_dma_irq_enable(&sun_pci_fd_ebus_dma, 0);
+}
+
+static int sun_pci_fd_eject(int drive)
+{
+ return -EINVAL;
+}
+
+void sun_pci_fd_dma_callback(struct ebus_dma_info *p, int event, void *cookie)
+{
+ floppy_interrupt(0, NULL);
+}
+
+/*
+ * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
+ * even if this is configured using DS1, thus looks like /dev/fd1 with
+ * the cabling used in Ultras.
+ */
+#define DOR (port + 2)
+#define MSR (port + 4)
+#define FIFO (port + 5)
+
+static void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
+ unsigned long reg)
+{
+ unsigned char status;
+ int timeout = 1000;
+
+ while (!((status = inb(MSR)) & 0x80) && --timeout)
+ udelay(100);
+ outb(val, reg);
+}
+
+static unsigned char sun_pci_fd_sensei(unsigned long port)
+{
+ unsigned char result[2] = { 0x70, 0x00 };
+ unsigned char status;
+ int i = 0;
+
+ sun_pci_fd_out_byte(port, 0x08, FIFO);
+ do {
+ int timeout = 1000;
+
+ while (!((status = inb(MSR)) & 0x80) && --timeout)
+ udelay(100);
+
+ if (!timeout)
+ break;
+
+ if ((status & 0xf0) == 0xd0)
+ result[i++] = inb(FIFO);
+ else
+ break;
+ } while (i < 2);
+
+ return result[0];
+}
+
+static void sun_pci_fd_reset(unsigned long port)
+{
+ unsigned char mask = 0x00;
+ unsigned char status;
+ int timeout = 10000;
+
+ outb(0x80, MSR);
+ do {
+ status = sun_pci_fd_sensei(port);
+ if ((status & 0xc0) == 0xc0)
+ mask |= 1 << (status & 0x03);
+ else
+ udelay(100);
+ } while ((mask != 0x0f) && --timeout);
+}
+
+static int sun_pci_fd_test_drive(unsigned long port, int drive)
+{
+ unsigned char status, data;
+ int timeout = 1000;
+ int ready;
+
+ sun_pci_fd_reset(port);
+
+ data = (0x10 << drive) | 0x0c | drive;
+ sun_pci_fd_out_byte(port, data, DOR);
+
+ sun_pci_fd_out_byte(port, 0x07, FIFO);
+ sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
+
+ do {
+ udelay(100);
+ status = sun_pci_fd_sensei(port);
+ } while (((status & 0xc0) == 0x80) && --timeout);
+
+ if (!timeout)
+ ready = 0;
+ else
+ ready = (status & 0x10) ? 0 : 1;
+
+ sun_pci_fd_reset(port);
+ return ready;
+}
+#undef FIFO
+#undef MSR
+#undef DOR
+
+static int __init ebus_fdthree_p(struct device_node *dp)
+{
+ if (of_node_name_eq(dp, "fdthree"))
+ return 1;
+ if (of_node_name_eq(dp, "floppy")) {
+ const char *compat;
+
+ compat = of_get_property(dp, "compatible", NULL);
+ if (compat && !strcmp(compat, "fdthree"))
+ return 1;
+ }
+ return 0;
+}
+
+static unsigned long __init sun_floppy_init(void)
+{
+ static int initialized = 0;
+ struct device_node *dp;
+ struct platform_device *op;
+ const char *prop;
+ char state[128];
+
+ if (initialized)
+ return sun_floppy_types[0];
+ initialized = 1;
+
+ op = NULL;
+
+ for_each_node_by_name(dp, "SUNW,fdtwo") {
+ if (!of_node_name_eq(dp->parent, "sbus"))
+ continue;
+ op = of_find_device_by_node(dp);
+ if (op)
+ break;
+ }
+ if (op) {
+ floppy_op = op;
+ FLOPPY_IRQ = op->archdata.irqs[0];
+ } else {
+ struct device_node *ebus_dp;
+ void __iomem *auxio_reg;
+ const char *state_prop;
+ unsigned long config;
+
+ dp = NULL;
+ for_each_node_by_name(ebus_dp, "ebus") {
+ for (dp = ebus_dp->child; dp; dp = dp->sibling) {
+ if (ebus_fdthree_p(dp))
+ goto found_fdthree;
+ }
+ }
+ found_fdthree:
+ if (!dp)
+ return 0;
+
+ op = of_find_device_by_node(dp);
+ if (!op)
+ return 0;
+
+ state_prop = of_get_property(op->dev.of_node, "status", NULL);
+ if (state_prop && !strncmp(state_prop, "disabled", 8))
+ return 0;
+
+ FLOPPY_IRQ = op->archdata.irqs[0];
+
+ /* Make sure the high density bit is set, some systems
+ * (most notably Ultra5/Ultra10) come up with it clear.
+ */
+ auxio_reg = (void __iomem *) op->resource[2].start;
+ writel(readl(auxio_reg)|0x2, auxio_reg);
+
+ sun_floppy_dev = &op->dev;
+
+ spin_lock_init(&sun_pci_fd_ebus_dma.lock);
+
+ /* XXX ioremap */
+ sun_pci_fd_ebus_dma.regs = (void __iomem *)
+ op->resource[1].start;
+ if (!sun_pci_fd_ebus_dma.regs)
+ return 0;
+
+ sun_pci_fd_ebus_dma.flags = (EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
+ EBUS_DMA_FLAG_TCI_DISABLE);
+ sun_pci_fd_ebus_dma.callback = sun_pci_fd_dma_callback;
+ sun_pci_fd_ebus_dma.client_cookie = NULL;
+ sun_pci_fd_ebus_dma.irq = FLOPPY_IRQ;
+ strcpy(sun_pci_fd_ebus_dma.name, "floppy");
+ if (ebus_dma_register(&sun_pci_fd_ebus_dma))
+ return 0;
+
+ /* XXX ioremap */
+ sun_fdc = (struct sun_flpy_controller *) op->resource[0].start;
+
+ sun_fdops.fd_inb = sun_pci_fd_inb;
+ sun_fdops.fd_outb = sun_pci_fd_outb;
+
+ can_use_virtual_dma = use_virtual_dma = 0;
+ sun_fdops.fd_enable_dma = sun_pci_fd_enable_dma;
+ sun_fdops.fd_disable_dma = sun_pci_fd_disable_dma;
+ sun_fdops.fd_set_dma_mode = sun_pci_fd_set_dma_mode;
+ sun_fdops.fd_set_dma_addr = sun_pci_fd_set_dma_addr;
+ sun_fdops.fd_set_dma_count = sun_pci_fd_set_dma_count;
+ sun_fdops.get_dma_residue = sun_pci_get_dma_residue;
+
+ sun_fdops.fd_request_irq = sun_pci_fd_request_irq;
+ sun_fdops.fd_free_irq = sun_pci_fd_free_irq;
+
+ sun_fdops.fd_eject = sun_pci_fd_eject;
+
+ fdc_status = (unsigned long) &sun_fdc->status_82077;
+
+ /*
+ * XXX: Find out on which machines this is really needed.
+ */
+ if (1) {
+ sun_pci_broken_drive = 1;
+ sun_fdops.fd_outb = sun_pci_fd_broken_outb;
+ }
+
+ allowed_drive_mask = 0;
+ if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
+ sun_floppy_types[0] = 4;
+ if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
+ sun_floppy_types[1] = 4;
+
+ /*
+ * Find NS87303 SuperIO config registers (through ecpp).
+ */
+ config = 0;
+ for (dp = ebus_dp->child; dp; dp = dp->sibling) {
+ if (of_node_name_eq(dp, "ecpp")) {
+ struct platform_device *ecpp_op;
+
+ ecpp_op = of_find_device_by_node(dp);
+ if (ecpp_op)
+ config = ecpp_op->resource[1].start;
+ goto config_done;
+ }
+ }
+ config_done:
+
+ /*
+ * Sanity check, is this really the NS87303?
+ */
+ switch (config & 0x3ff) {
+ case 0x02e:
+ case 0x15c:
+ case 0x26e:
+ case 0x398:
+ break;
+ default:
+ config = 0;
+ }
+
+ if (!config)
+ return sun_floppy_types[0];
+
+ /* Enable PC-AT mode. */
+ ns87303_modify(config, ASC, 0, 0xc0);
+
+#ifdef PCI_FDC_SWAP_DRIVES
+ /*
+ * If only Floppy 1 is present, swap drives.
+ */
+ if (!sun_floppy_types[0] && sun_floppy_types[1]) {
+ /*
+ * Set the drive exchange bit in FCR on NS87303,
+ * make sure other bits are sane before doing so.
+ */
+ ns87303_modify(config, FER, FER_EDM, 0);
+ ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
+ ns87303_modify(config, FCR, 0, FCR_LDE);
+
+ config = sun_floppy_types[0];
+ sun_floppy_types[0] = sun_floppy_types[1];
+ sun_floppy_types[1] = config;
+
+ if (sun_pci_broken_drive != -1) {
+ sun_pci_broken_drive = 1 - sun_pci_broken_drive;
+ sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
+ }
+ }
+#endif /* PCI_FDC_SWAP_DRIVES */
+
+ return sun_floppy_types[0];
+ }
+ prop = of_get_property(op->dev.of_node, "status", NULL);
+ if (prop && !strncmp(state, "disabled", 8))
+ return 0;
+
+ /*
+ * We cannot do of_ioremap here: it does request_region,
+ * which the generic floppy driver tries to do once again.
+ * But we must use the sdev resource values as they have
+ * had parent ranges applied.
+ */
+ sun_fdc = (struct sun_flpy_controller *)
+ (op->resource[0].start +
+ ((op->resource[0].flags & 0x1ffUL) << 32UL));
+
+ /* Last minute sanity check... */
+ if (sbus_readb(&sun_fdc->status1_82077) == 0xff) {
+ sun_fdc = (struct sun_flpy_controller *)-1;
+ return 0;
+ }
+
+ sun_fdops.fd_inb = sun_82077_fd_inb;
+ sun_fdops.fd_outb = sun_82077_fd_outb;
+
+ can_use_virtual_dma = use_virtual_dma = 1;
+ sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+ sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+ sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+ sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+ sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+ sun_fdops.get_dma_residue = sun_get_dma_residue;
+
+ sun_fdops.fd_request_irq = sun_fd_request_irq;
+ sun_fdops.fd_free_irq = sun_fd_free_irq;
+
+ sun_fdops.fd_eject = sun_fd_eject;
+
+ fdc_status = (unsigned long) &sun_fdc->status_82077;
+
+ /* Success... */
+ allowed_drive_mask = 0x01;
+ sun_floppy_types[0] = 4;
+ sun_floppy_types[1] = 0;
+
+ return sun_floppy_types[0];
+}
+
+#define EXTRA_FLOPPY_PARAMS
+
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({ unsigned long flags; \
+ spin_lock_irqsave(&dma_spin_lock, flags); \
+ flags; \
+})
+
+#define release_dma_lock(__flags) \
+ spin_unlock_irqrestore(&dma_spin_lock, __flags);
+
+#endif /* !(__ASM_SPARC64_FLOPPY_H) */
diff --git a/arch/sparc/include/asm/fpumacro.h b/arch/sparc/include/asm/fpumacro.h
new file mode 100644
index 000000000..bc378df97
--- /dev/null
+++ b/arch/sparc/include/asm/fpumacro.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* fpumacro.h: FPU related macros.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC64_FPUMACRO_H
+#define _SPARC64_FPUMACRO_H
+
+#include <asm/asi.h>
+#include <asm/visasm.h>
+
+struct fpustate {
+ u32 regs[64];
+};
+
+#define FPUSTATE (struct fpustate *)(current_thread_info()->fpregs)
+
+static inline unsigned long fprs_read(void)
+{
+ unsigned long retval;
+
+ __asm__ __volatile__("rd %%fprs, %0" : "=r" (retval));
+
+ return retval;
+}
+
+static inline void fprs_write(unsigned long val)
+{
+ __asm__ __volatile__("wr %0, 0x0, %%fprs" : : "r" (val));
+}
+
+#endif /* !(_SPARC64_FPUMACRO_H) */
diff --git a/arch/sparc/include/asm/ftrace.h b/arch/sparc/include/asm/ftrace.h
new file mode 100644
index 000000000..e284394cb
--- /dev/null
+++ b/arch/sparc/include/asm/ftrace.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC64_FTRACE
+#define _ASM_SPARC64_FTRACE
+
+#ifdef CONFIG_MCOUNT
+#define MCOUNT_ADDR ((unsigned long)(_mcount))
+#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
+
+#ifndef __ASSEMBLY__
+void _mcount(void);
+#endif
+
+#endif /* CONFIG_MCOUNT */
+
+#if defined(CONFIG_SPARC64) && !defined(CC_USE_FENTRY)
+#define HAVE_FUNCTION_GRAPH_FP_TEST
+#endif
+
+#ifdef CONFIG_DYNAMIC_FTRACE
+/* relocation of mcount call site is the same as the address */
+static inline unsigned long ftrace_call_adjust(unsigned long addr)
+{
+ return addr;
+}
+
+struct dyn_arch_ftrace {
+};
+#endif /* CONFIG_DYNAMIC_FTRACE */
+
+unsigned long prepare_ftrace_return(unsigned long parent,
+ unsigned long self_addr,
+ unsigned long frame_pointer);
+
+#endif /* _ASM_SPARC64_FTRACE */
diff --git a/arch/sparc/include/asm/futex.h b/arch/sparc/include/asm/futex.h
new file mode 100644
index 000000000..75a13a20c
--- /dev/null
+++ b/arch/sparc/include/asm/futex.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_FUTEX_H
+#define ___ASM_SPARC_FUTEX_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/futex_64.h>
+#else
+#include <asm/futex_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/futex_32.h b/arch/sparc/include/asm/futex_32.h
new file mode 100644
index 000000000..6a332a9f0
--- /dev/null
+++ b/arch/sparc/include/asm/futex_32.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_FUTEX_H
+#define _ASM_FUTEX_H
+
+#include <asm-generic/futex.h>
+
+#endif
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
new file mode 100644
index 000000000..72de96731
--- /dev/null
+++ b/arch/sparc/include/asm/futex_64.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_FUTEX_H
+#define _SPARC64_FUTEX_H
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+#define __futex_cas_op(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile__( \
+ "\n1: lduwa [%3] %%asi, %2\n" \
+ " " insn "\n" \
+ "2: casa [%3] %%asi, %2, %1\n" \
+ " cmp %2, %1\n" \
+ " bne,pn %%icc, 1b\n" \
+ " mov 0, %0\n" \
+ "3:\n" \
+ " .section .fixup,#alloc,#execinstr\n" \
+ " .align 4\n" \
+ "4: sethi %%hi(3b), %0\n" \
+ " jmpl %0 + %%lo(3b), %%g0\n" \
+ " mov %5, %0\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .align 4\n" \
+ " .word 1b, 4b\n" \
+ " .word 2b, 4b\n" \
+ " .previous\n" \
+ : "=&r" (ret), "=&r" (oldval), "=&r" (tem) \
+ : "r" (uaddr), "r" (oparg), "i" (-EFAULT) \
+ : "memory")
+
+static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
+ u32 __user *uaddr)
+{
+ int oldval = 0, ret, tem;
+
+ if (unlikely((((unsigned long) uaddr) & 0x3UL)))
+ return -EINVAL;
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_cas_op("mov\t%4, %1", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_cas_op("add\t%2, %4, %1", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_cas_op("or\t%2, %4, %1", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_cas_op("andn\t%2, %4, %1", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_cas_op("xor\t%2, %4, %1", ret, oldval, uaddr, oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ if (!ret)
+ *oval = oldval;
+
+ return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+ u32 oldval, u32 newval)
+{
+ int ret = 0;
+
+ __asm__ __volatile__(
+ "\n1: casa [%4] %%asi, %3, %1\n"
+ "2:\n"
+ " .section .fixup,#alloc,#execinstr\n"
+ " .align 4\n"
+ "3: sethi %%hi(2b), %0\n"
+ " jmpl %0 + %%lo(2b), %%g0\n"
+ " mov %5, %0\n"
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .align 4\n"
+ " .word 1b, 3b\n"
+ " .previous\n"
+ : "+r" (ret), "=r" (newval)
+ : "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+ : "memory");
+
+ *uval = newval;
+ return ret;
+}
+
+#endif /* !(_SPARC64_FUTEX_H) */
diff --git a/arch/sparc/include/asm/hardirq.h b/arch/sparc/include/asm/hardirq.h
new file mode 100644
index 000000000..a185f6647
--- /dev/null
+++ b/arch/sparc/include/asm/hardirq.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_HARDIRQ_H
+#define ___ASM_SPARC_HARDIRQ_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/hardirq_64.h>
+#else
+#include <asm/hardirq_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/hardirq_32.h b/arch/sparc/include/asm/hardirq_32.h
new file mode 100644
index 000000000..9830d8731
--- /dev/null
+++ b/arch/sparc/include/asm/hardirq_32.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* hardirq.h: 32-bit Sparc hard IRQ support.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
+ */
+
+#ifndef __SPARC_HARDIRQ_H
+#define __SPARC_HARDIRQ_H
+
+#include <asm-generic/hardirq.h>
+
+#endif /* __SPARC_HARDIRQ_H */
diff --git a/arch/sparc/include/asm/hardirq_64.h b/arch/sparc/include/asm/hardirq_64.h
new file mode 100644
index 000000000..75b92bfe0
--- /dev/null
+++ b/arch/sparc/include/asm/hardirq_64.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* hardirq.h: 64-bit Sparc hard IRQ support.
+ *
+ * Copyright (C) 1997, 1998, 2005 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef __SPARC64_HARDIRQ_H
+#define __SPARC64_HARDIRQ_H
+
+#include <asm/cpudata.h>
+
+#define __ARCH_IRQ_STAT
+
+#define local_softirq_pending_ref \
+ __cpu_data.__softirq_pending
+
+void ack_bad_irq(unsigned int irq);
+
+#endif /* !(__SPARC64_HARDIRQ_H) */
diff --git a/arch/sparc/include/asm/head.h b/arch/sparc/include/asm/head.h
new file mode 100644
index 000000000..25299b701
--- /dev/null
+++ b/arch/sparc/include/asm/head.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_HEAD_H
+#define ___ASM_SPARC_HEAD_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/head_64.h>
+#else
+#include <asm/head_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/head_32.h b/arch/sparc/include/asm/head_32.h
new file mode 100644
index 000000000..d2809c859
--- /dev/null
+++ b/arch/sparc/include/asm/head_32.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_HEAD_H
+#define __SPARC_HEAD_H
+
+#define KERNBASE 0xf0000000 /* First address the kernel will eventually be */
+
+#define WRITE_PAUSE nop; nop; nop; /* Have to do this after %wim/%psr chg */
+
+/* Here are some trap goodies */
+
+/* Generic trap entry. */
+#define TRAP_ENTRY(type, label) \
+ rd %psr, %l0; b label; rd %wim, %l3; nop;
+
+/* Data/text faults */
+#define SRMMU_TFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 1, %l7;
+#define SRMMU_DFAULT rd %psr, %l0; rd %wim, %l3; b srmmu_fault; mov 0, %l7;
+
+/* This is for traps we should NEVER get. */
+#define BAD_TRAP(num) \
+ rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3;
+
+/* This is for traps when we want just skip the instruction which caused it */
+#define SKIP_TRAP(type, name) \
+ jmpl %l2, %g0; rett %l2 + 4; nop; nop;
+
+/* Notice that for the system calls we pull a trick. We load up a
+ * different pointer to the system call vector table in %l7, but call
+ * the same generic system call low-level entry point. The trap table
+ * entry sequences are also HyperSparc pipeline friendly ;-)
+ */
+
+/* Software trap for Linux system calls. */
+#define LINUX_SYSCALL_TRAP \
+ sethi %hi(sys_call_table), %l7; \
+ or %l7, %lo(sys_call_table), %l7; \
+ b linux_sparc_syscall; \
+ rd %psr, %l0;
+
+#define BREAKPOINT_TRAP \
+ b breakpoint_trap; \
+ rd %psr,%l0; \
+ nop; \
+ nop;
+
+#ifdef CONFIG_KGDB
+#define KGDB_TRAP(num) \
+ mov num, %l7; \
+ b kgdb_trap_low; \
+ rd %psr,%l0; \
+ nop;
+#else
+#define KGDB_TRAP(num) \
+ BAD_TRAP(num)
+#endif
+
+/* The Get Condition Codes software trap for userland. */
+#define GETCC_TRAP \
+ b getcc_trap_handler; rd %psr, %l0; nop; nop;
+
+/* The Set Condition Codes software trap for userland. */
+#define SETCC_TRAP \
+ b setcc_trap_handler; rd %psr, %l0; nop; nop;
+
+/* The Get PSR software trap for userland. */
+#define GETPSR_TRAP \
+ rd %psr, %i0; jmp %l2; rett %l2 + 4; nop;
+
+/* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
+ * gets handled with another macro.
+ */
+#define TRAP_ENTRY_INTERRUPT(int_level) \
+ mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
+
+/* Window overflows/underflows are special and we need to try to be as
+ * efficient as possible here....
+ */
+#define WINDOW_SPILL \
+ rd %psr, %l0; rd %wim, %l3; b spill_window_entry; andcc %l0, PSR_PS, %g0;
+
+#define WINDOW_FILL \
+ rd %psr, %l0; rd %wim, %l3; b fill_window_entry; andcc %l0, PSR_PS, %g0;
+
+#endif /* __SPARC_HEAD_H */
diff --git a/arch/sparc/include/asm/head_64.h b/arch/sparc/include/asm/head_64.h
new file mode 100644
index 000000000..69a2062d9
--- /dev/null
+++ b/arch/sparc/include/asm/head_64.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_HEAD_H
+#define _SPARC64_HEAD_H
+
+#include <asm/pstate.h>
+
+ /* wrpr %g0, val, %gl */
+#define SET_GL(val) \
+ .word 0xa1902000 | val
+
+ /* rdpr %gl, %gN */
+#define GET_GL_GLOBAL(N) \
+ .word 0x81540000 | (N << 25)
+
+#define KERNBASE 0x400000
+
+#define PTREGS_OFF (STACK_BIAS + STACKFRAME_SZ)
+
+#define RTRAP_PSTATE (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
+#define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
+#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
+
+#define __CHEETAH_ID 0x003e0014
+#define __JALAPENO_ID 0x003e0016
+#define __SERRANO_ID 0x003e0022
+
+#define CHEETAH_MANUF 0x003e
+#define CHEETAH_IMPL 0x0014 /* Ultra-III */
+#define CHEETAH_PLUS_IMPL 0x0015 /* Ultra-III+ */
+#define JALAPENO_IMPL 0x0016 /* Ultra-IIIi */
+#define JAGUAR_IMPL 0x0018 /* Ultra-IV */
+#define PANTHER_IMPL 0x0019 /* Ultra-IV+ */
+#define SERRANO_IMPL 0x0022 /* Ultra-IIIi+ */
+
+#define BRANCH_IF_SUN4V(tmp1,label) \
+ sethi %hi(is_sun4v), %tmp1; \
+ lduw [%tmp1 + %lo(is_sun4v)], %tmp1; \
+ brnz,pn %tmp1, label; \
+ nop
+
+#define BRANCH_IF_CHEETAH_BASE(tmp1,tmp2,label) \
+ rdpr %ver, %tmp1; \
+ sethi %hi(__CHEETAH_ID), %tmp2; \
+ srlx %tmp1, 32, %tmp1; \
+ or %tmp2, %lo(__CHEETAH_ID), %tmp2;\
+ cmp %tmp1, %tmp2; \
+ be,pn %icc, label; \
+ nop;
+
+#define BRANCH_IF_JALAPENO(tmp1,tmp2,label) \
+ rdpr %ver, %tmp1; \
+ sethi %hi(__JALAPENO_ID), %tmp2; \
+ srlx %tmp1, 32, %tmp1; \
+ or %tmp2, %lo(__JALAPENO_ID), %tmp2;\
+ cmp %tmp1, %tmp2; \
+ be,pn %icc, label; \
+ nop;
+
+#define BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(tmp1,tmp2,label) \
+ rdpr %ver, %tmp1; \
+ srlx %tmp1, (32 + 16), %tmp2; \
+ cmp %tmp2, CHEETAH_MANUF; \
+ bne,pt %xcc, 99f; \
+ sllx %tmp1, 16, %tmp1; \
+ srlx %tmp1, (32 + 16), %tmp2; \
+ cmp %tmp2, CHEETAH_PLUS_IMPL; \
+ bgeu,pt %xcc, label; \
+99: nop;
+
+#define BRANCH_IF_ANY_CHEETAH(tmp1,tmp2,label) \
+ rdpr %ver, %tmp1; \
+ srlx %tmp1, (32 + 16), %tmp2; \
+ cmp %tmp2, CHEETAH_MANUF; \
+ bne,pt %xcc, 99f; \
+ sllx %tmp1, 16, %tmp1; \
+ srlx %tmp1, (32 + 16), %tmp2; \
+ cmp %tmp2, CHEETAH_IMPL; \
+ bgeu,pt %xcc, label; \
+99: nop;
+
+#endif /* !(_SPARC64_HEAD_H) */
diff --git a/arch/sparc/include/asm/hibernate.h b/arch/sparc/include/asm/hibernate.h
new file mode 100644
index 000000000..3bb0a96ec
--- /dev/null
+++ b/arch/sparc/include/asm/hibernate.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * hibernate.h: Hibernaton support specific for sparc64.
+ *
+ * Copyright (C) 2013 Kirill V Tkhai (tkhai@yandex.ru)
+ */
+
+#ifndef ___SPARC_HIBERNATE_H
+#define ___SPARC_HIBERNATE_H
+
+struct saved_context {
+ unsigned long fp;
+ unsigned long cwp;
+ unsigned long wstate;
+
+ unsigned long tick;
+ unsigned long pstate;
+
+ unsigned long g4;
+ unsigned long g5;
+ unsigned long g6;
+};
+
+#endif
diff --git a/arch/sparc/include/asm/highmem.h b/arch/sparc/include/asm/highmem.h
new file mode 100644
index 000000000..c7b2e2083
--- /dev/null
+++ b/arch/sparc/include/asm/highmem.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * highmem.h: virtual kernel memory mappings for high memory
+ *
+ * Used in CONFIG_HIGHMEM systems for memory pages which
+ * are not addressable by direct kernel virtual addresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ * Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with
+ * up to 16 Terrabyte physical memory. With current x86 CPUs
+ * we now support up to 64 Gigabytes physical RAM.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+#ifndef _ASM_HIGHMEM_H
+#define _ASM_HIGHMEM_H
+
+#ifdef __KERNEL__
+
+#include <linux/interrupt.h>
+#include <linux/pgtable.h>
+#include <asm/vaddrs.h>
+#include <asm/pgtsrmmu.h>
+
+/* declarations for highmem.c */
+extern unsigned long highstart_pfn, highend_pfn;
+
+#define kmap_prot __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE)
+extern pte_t *pkmap_page_table;
+
+/*
+ * Right now we initialize only a single pte table. It can be extended
+ * easily, subsequent pte tables have to be allocated in one physical
+ * chunk of RAM. Currently the simplest way to do this is to align the
+ * pkmap region on a pagetable boundary (4MB).
+ */
+#define LAST_PKMAP 1024
+#define PKMAP_SIZE (LAST_PKMAP << PAGE_SHIFT)
+#define PKMAP_BASE PMD_ALIGN(SRMMU_NOCACHE_VADDR + (SRMMU_MAX_NOCACHE_PAGES << PAGE_SHIFT))
+
+#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
+#define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT)
+#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+
+#define PKMAP_END (PKMAP_ADDR(LAST_PKMAP))
+
+#define flush_cache_kmaps() flush_cache_all()
+
+/* FIXME: Use __flush_*_one(vaddr) instead of flush_*_all() -- Anton */
+#define arch_kmap_local_pre_map(vaddr, pteval) flush_cache_all()
+#define arch_kmap_local_pre_unmap(vaddr) flush_cache_all()
+#define arch_kmap_local_post_map(vaddr, pteval) flush_tlb_all()
+#define arch_kmap_local_post_unmap(vaddr) flush_tlb_all()
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_HIGHMEM_H */
diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h
new file mode 100644
index 000000000..c714ca6a0
--- /dev/null
+++ b/arch/sparc/include/asm/hugetlb.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC64_HUGETLB_H
+#define _ASM_SPARC64_HUGETLB_H
+
+#include <asm/page.h>
+
+#ifdef CONFIG_HUGETLB_PAGE
+struct pud_huge_patch_entry {
+ unsigned int addr;
+ unsigned int insn;
+};
+extern struct pud_huge_patch_entry __pud_huge_patch, __pud_huge_patch_end;
+#endif
+
+#define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte, unsigned long sz);
+void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
+
+#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep);
+
+#define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
+static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep)
+{
+ return *ptep;
+}
+
+#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
+static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ pte_t old_pte = *ptep;
+ __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
+}
+
+#define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
+static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ int changed = !pte_same(*ptep, pte);
+ if (changed) {
+ __set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+ flush_tlb_page(vma, addr);
+ }
+ return changed;
+}
+
+#define __HAVE_ARCH_HUGETLB_FREE_PGD_RANGE
+void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
+ unsigned long end, unsigned long floor,
+ unsigned long ceiling);
+
+#include <asm-generic/hugetlb.h>
+
+#endif /* _ASM_SPARC64_HUGETLB_H */
diff --git a/arch/sparc/include/asm/hvtramp.h b/arch/sparc/include/asm/hvtramp.h
new file mode 100644
index 000000000..688ea43af
--- /dev/null
+++ b/arch/sparc/include/asm/hvtramp.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_HVTRAP_H
+#define _SPARC64_HVTRAP_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct hvtramp_mapping {
+ __u64 vaddr;
+ __u64 tte;
+};
+
+struct hvtramp_descr {
+ __u32 cpu;
+ __u32 num_mappings;
+ __u64 fault_info_va;
+ __u64 fault_info_pa;
+ __u64 thread_reg;
+ struct hvtramp_mapping maps[1];
+};
+
+void hv_cpu_startup(unsigned long hvdescr_pa);
+
+#endif
+
+#define HVTRAMP_DESCR_CPU 0x00
+#define HVTRAMP_DESCR_NUM_MAPPINGS 0x04
+#define HVTRAMP_DESCR_FAULT_INFO_VA 0x08
+#define HVTRAMP_DESCR_FAULT_INFO_PA 0x10
+#define HVTRAMP_DESCR_THREAD_REG 0x18
+#define HVTRAMP_DESCR_MAPS 0x20
+
+#define HVTRAMP_MAPPING_VADDR 0x00
+#define HVTRAMP_MAPPING_TTE 0x08
+#define HVTRAMP_MAPPING_SIZE 0x10
+
+#endif /* _SPARC64_HVTRAP_H */
diff --git a/arch/sparc/include/asm/hw_irq.h b/arch/sparc/include/asm/hw_irq.h
new file mode 100644
index 000000000..8d30a7694
--- /dev/null
+++ b/arch/sparc/include/asm/hw_irq.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_SPARC_HW_IRQ_H
+#define __ASM_SPARC_HW_IRQ_H
+
+/* Dummy include. */
+
+#endif
diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h
new file mode 100644
index 000000000..08650d503
--- /dev/null
+++ b/arch/sparc/include/asm/hypervisor.h
@@ -0,0 +1,3527 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_HYPERVISOR_H
+#define _SPARC64_HYPERVISOR_H
+
+/* Sun4v hypervisor interfaces and defines.
+ *
+ * Hypervisor calls are made via traps to software traps number 0x80
+ * and above. Registers %o0 to %o5 serve as argument, status, and
+ * return value registers.
+ *
+ * There are two kinds of these traps. First there are the normal
+ * "fast traps" which use software trap 0x80 and encode the function
+ * to invoke by number in register %o5. Argument and return value
+ * handling is as follows:
+ *
+ * -----------------------------------------------
+ * | %o5 | function number | undefined |
+ * | %o0 | argument 0 | return status |
+ * | %o1 | argument 1 | return value 1 |
+ * | %o2 | argument 2 | return value 2 |
+ * | %o3 | argument 3 | return value 3 |
+ * | %o4 | argument 4 | return value 4 |
+ * -----------------------------------------------
+ *
+ * The second type are "hyper-fast traps" which encode the function
+ * number in the software trap number itself. So these use trap
+ * numbers > 0x80. The register usage for hyper-fast traps is as
+ * follows:
+ *
+ * -----------------------------------------------
+ * | %o0 | argument 0 | return status |
+ * | %o1 | argument 1 | return value 1 |
+ * | %o2 | argument 2 | return value 2 |
+ * | %o3 | argument 3 | return value 3 |
+ * | %o4 | argument 4 | return value 4 |
+ * -----------------------------------------------
+ *
+ * Registers providing explicit arguments to the hypervisor calls
+ * are volatile across the call. Upon return their values are
+ * undefined unless explicitly specified as containing a particular
+ * return value by the specific call. The return status is always
+ * returned in register %o0, zero indicates a successful execution of
+ * the hypervisor call and other values indicate an error status as
+ * defined below. So, for example, if a hyper-fast trap takes
+ * arguments 0, 1, and 2, then %o0, %o1, and %o2 are volatile across
+ * the call and %o3, %o4, and %o5 would be preserved.
+ *
+ * If the hypervisor trap is invalid, or the fast trap function number
+ * is invalid, HV_EBADTRAP will be returned in %o0. Also, all 64-bits
+ * of the argument and return values are significant.
+ */
+
+/* Trap numbers. */
+#define HV_FAST_TRAP 0x80
+#define HV_MMU_MAP_ADDR_TRAP 0x83
+#define HV_MMU_UNMAP_ADDR_TRAP 0x84
+#define HV_TTRACE_ADDENTRY_TRAP 0x85
+#define HV_CORE_TRAP 0xff
+
+/* Error codes. */
+#define HV_EOK 0 /* Successful return */
+#define HV_ENOCPU 1 /* Invalid CPU id */
+#define HV_ENORADDR 2 /* Invalid real address */
+#define HV_ENOINTR 3 /* Invalid interrupt id */
+#define HV_EBADPGSZ 4 /* Invalid pagesize encoding */
+#define HV_EBADTSB 5 /* Invalid TSB description */
+#define HV_EINVAL 6 /* Invalid argument */
+#define HV_EBADTRAP 7 /* Invalid function number */
+#define HV_EBADALIGN 8 /* Invalid address alignment */
+#define HV_EWOULDBLOCK 9 /* Cannot complete w/o blocking */
+#define HV_ENOACCESS 10 /* No access to resource */
+#define HV_EIO 11 /* I/O error */
+#define HV_ECPUERROR 12 /* CPU in error state */
+#define HV_ENOTSUPPORTED 13 /* Function not supported */
+#define HV_ENOMAP 14 /* No mapping found */
+#define HV_ETOOMANY 15 /* Too many items specified */
+#define HV_ECHANNEL 16 /* Invalid LDC channel */
+#define HV_EBUSY 17 /* Resource busy */
+#define HV_EUNAVAILABLE 23 /* Resource or operation not
+ * currently available, but may
+ * become available in the future
+ */
+
+/* mach_exit()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_EXIT
+ * ARG0: exit code
+ * ERRORS: This service does not return.
+ *
+ * Stop all CPUs in the virtual domain and place them into the stopped
+ * state. The 64-bit exit code may be passed to a service entity as
+ * the domain's exit status. On systems without a service entity, the
+ * domain will undergo a reset, and the boot firmware will be
+ * reloaded.
+ *
+ * This function will never return to the guest that invokes it.
+ *
+ * Note: By convention an exit code of zero denotes a successful exit by
+ * the guest code. A non-zero exit code denotes a guest specific
+ * error indication.
+ *
+ */
+#define HV_FAST_MACH_EXIT 0x00
+
+#ifndef __ASSEMBLY__
+void sun4v_mach_exit(unsigned long exit_code);
+#endif
+
+/* Domain services. */
+
+/* mach_desc()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_DESC
+ * ARG0: buffer
+ * ARG1: length
+ * RET0: status
+ * RET1: length
+ * ERRORS: HV_EBADALIGN Buffer is badly aligned
+ * HV_ENORADDR Buffer is to an illegal real address.
+ * HV_EINVAL Buffer length is too small for complete
+ * machine description.
+ *
+ * Copy the most current machine description into the buffer indicated
+ * by the real address in ARG0. The buffer provided must be 16 byte
+ * aligned. Upon success or HV_EINVAL, this service returns the
+ * actual size of the machine description in the RET1 return value.
+ *
+ * Note: A method of determining the appropriate buffer size for the
+ * machine description is to first call this service with a buffer
+ * length of 0 bytes.
+ */
+#define HV_FAST_MACH_DESC 0x01
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mach_desc(unsigned long buffer_pa,
+ unsigned long buf_len,
+ unsigned long *real_buf_len);
+#endif
+
+/* mach_sir()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_SIR
+ * ERRORS: This service does not return.
+ *
+ * Perform a software initiated reset of the virtual machine domain.
+ * All CPUs are captured as soon as possible, all hardware devices are
+ * returned to the entry default state, and the domain is restarted at
+ * the SIR (trap type 0x04) real trap table (RTBA) entry point on one
+ * of the CPUs. The single CPU restarted is selected as determined by
+ * platform specific policy. Memory is preserved across this
+ * operation.
+ */
+#define HV_FAST_MACH_SIR 0x02
+
+#ifndef __ASSEMBLY__
+void sun4v_mach_sir(void);
+#endif
+
+/* mach_set_watchdog()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_SET_WATCHDOG
+ * ARG0: timeout in milliseconds
+ * RET0: status
+ * RET1: time remaining in milliseconds
+ *
+ * A guest uses this API to set a watchdog timer. Once the gues has set
+ * the timer, it must call the timer service again either to disable or
+ * postpone the expiration. If the timer expires before being reset or
+ * disabled, then the hypervisor take a platform specific action leading
+ * to guest termination within a bounded time period. The platform action
+ * may include recovery actions such as reporting the expiration to a
+ * Service Processor, and/or automatically restarting the gues.
+ *
+ * The 'timeout' parameter is specified in milliseconds, however the
+ * implementated granularity is given by the 'watchdog-resolution'
+ * property in the 'platform' node of the guest's machine description.
+ * The largest allowed timeout value is specified by the
+ * 'watchdog-max-timeout' property of the 'platform' node.
+ *
+ * If the 'timeout' argument is not zero, the watchdog timer is set to
+ * expire after a minimum of 'timeout' milliseconds.
+ *
+ * If the 'timeout' argument is zero, the watchdog timer is disabled.
+ *
+ * If the 'timeout' value exceeds the value of the 'max-watchdog-timeout'
+ * property, the hypervisor leaves the watchdog timer state unchanged,
+ * and returns a status of EINVAL.
+ *
+ * The 'time remaining' return value is valid regardless of whether the
+ * return status is EOK or EINVAL. A non-zero return value indicates the
+ * number of milliseconds that were remaining until the timer was to expire.
+ * If less than one millisecond remains, the return value is '1'. If the
+ * watchdog timer was disabled at the time of the call, the return value is
+ * zero.
+ *
+ * If the hypervisor cannot support the exact timeout value requested, but
+ * can support a larger timeout value, the hypervisor may round the actual
+ * timeout to a value larger than the requested timeout, consequently the
+ * 'time remaining' return value may be larger than the previously requested
+ * timeout value.
+ *
+ * Any guest OS debugger should be aware that the watchdog service may be in
+ * use. Consequently, it is recommended that the watchdog service is
+ * disabled upon debugger entry (e.g. reaching a breakpoint), and then
+ * re-enabled upon returning to normal execution. The API has been designed
+ * with this in mind, and the 'time remaining' result of the disable call may
+ * be used directly as the timeout argument of the re-enable call.
+ */
+#define HV_FAST_MACH_SET_WATCHDOG 0x05
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mach_set_watchdog(unsigned long timeout,
+ unsigned long *orig_timeout);
+#endif
+
+/* CPU services.
+ *
+ * CPUs represent devices that can execute software threads. A single
+ * chip that contains multiple cores or strands is represented as
+ * multiple CPUs with unique CPU identifiers. CPUs are exported to
+ * OBP via the machine description (and to the OS via the OBP device
+ * tree). CPUs are always in one of three states: stopped, running,
+ * or error.
+ *
+ * A CPU ID is a pre-assigned 16-bit value that uniquely identifies a
+ * CPU within a logical domain. Operations that are to be performed
+ * on multiple CPUs specify them via a CPU list. A CPU list is an
+ * array in real memory, of which each 16-bit word is a CPU ID. CPU
+ * lists are passed through the API as two arguments. The first is
+ * the number of entries (16-bit words) in the CPU list, and the
+ * second is the (real address) pointer to the CPU ID list.
+ */
+
+/* cpu_start()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_START
+ * ARG0: CPU ID
+ * ARG1: PC
+ * ARG2: RTBA
+ * ARG3: target ARG0
+ * RET0: status
+ * ERRORS: ENOCPU Invalid CPU ID
+ * EINVAL Target CPU ID is not in the stopped state
+ * ENORADDR Invalid PC or RTBA real address
+ * EBADALIGN Unaligned PC or unaligned RTBA
+ * EWOULDBLOCK Starting resources are not available
+ *
+ * Start CPU with given CPU ID with PC in %pc and with a real trap
+ * base address value of RTBA. The indicated CPU must be in the
+ * stopped state. The supplied RTBA must be aligned on a 256 byte
+ * boundary. On successful completion, the specified CPU will be in
+ * the running state and will be supplied with "target ARG0" in %o0
+ * and RTBA in %tba.
+ */
+#define HV_FAST_CPU_START 0x10
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_start(unsigned long cpuid,
+ unsigned long pc,
+ unsigned long rtba,
+ unsigned long arg0);
+#endif
+
+/* cpu_stop()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_STOP
+ * ARG0: CPU ID
+ * RET0: status
+ * ERRORS: ENOCPU Invalid CPU ID
+ * EINVAL Target CPU ID is the current cpu
+ * EINVAL Target CPU ID is not in the running state
+ * EWOULDBLOCK Stopping resources are not available
+ * ENOTSUPPORTED Not supported on this platform
+ *
+ * The specified CPU is stopped. The indicated CPU must be in the
+ * running state. On completion, it will be in the stopped state. It
+ * is not legal to stop the current CPU.
+ *
+ * Note: As this service cannot be used to stop the current cpu, this service
+ * may not be used to stop the last running CPU in a domain. To stop
+ * and exit a running domain, a guest must use the mach_exit() service.
+ */
+#define HV_FAST_CPU_STOP 0x11
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_stop(unsigned long cpuid);
+#endif
+
+/* cpu_yield()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_YIELD
+ * RET0: status
+ * ERRORS: No possible error.
+ *
+ * Suspend execution on the current CPU. Execution will resume when
+ * an interrupt (device, %stick_compare, or cross-call) is targeted to
+ * the CPU. On some CPUs, this API may be used by the hypervisor to
+ * save power by disabling hardware strands.
+ */
+#define HV_FAST_CPU_YIELD 0x12
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_yield(void);
+#endif
+
+/* cpu_poke()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_POKE
+ * RET0: status
+ * ERRORS: ENOCPU cpuid refers to a CPU that does not exist
+ * EINVAL cpuid is current CPU
+ *
+ * Poke CPU cpuid. If the target CPU is currently suspended having
+ * invoked the cpu-yield service, that vCPU will be resumed.
+ * Poke interrupts may only be sent to valid, non-local CPUs.
+ * It is not legal to poke the current vCPU.
+ */
+#define HV_FAST_CPU_POKE 0x13
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_poke(unsigned long cpuid);
+#endif
+
+/* cpu_qconf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_QCONF
+ * ARG0: queue
+ * ARG1: base real address
+ * ARG2: number of entries
+ * RET0: status
+ * ERRORS: ENORADDR Invalid base real address
+ * EINVAL Invalid queue or number of entries is less
+ * than 2 or too large.
+ * EBADALIGN Base real address is not correctly aligned
+ * for size.
+ *
+ * Configure the given queue to be placed at the given base real
+ * address, with the given number of entries. The number of entries
+ * must be a power of 2. The base real address must be aligned
+ * exactly to match the queue size. Each queue entry is 64 bytes
+ * long, so for example a 32 entry queue must be aligned on a 2048
+ * byte real address boundary.
+ *
+ * The specified queue is unconfigured if the number of entries is given
+ * as zero.
+ *
+ * For the current version of this API service, the argument queue is defined
+ * as follows:
+ *
+ * queue description
+ * ----- -------------------------
+ * 0x3c cpu mondo queue
+ * 0x3d device mondo queue
+ * 0x3e resumable error queue
+ * 0x3f non-resumable error queue
+ *
+ * Note: The maximum number of entries for each queue for a specific cpu may
+ * be determined from the machine description.
+ */
+#define HV_FAST_CPU_QCONF 0x14
+#define HV_CPU_QUEUE_CPU_MONDO 0x3c
+#define HV_CPU_QUEUE_DEVICE_MONDO 0x3d
+#define HV_CPU_QUEUE_RES_ERROR 0x3e
+#define HV_CPU_QUEUE_NONRES_ERROR 0x3f
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_qconf(unsigned long type,
+ unsigned long queue_paddr,
+ unsigned long num_queue_entries);
+#endif
+
+/* cpu_qinfo()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_QINFO
+ * ARG0: queue
+ * RET0: status
+ * RET1: base real address
+ * RET1: number of entries
+ * ERRORS: EINVAL Invalid queue
+ *
+ * Return the configuration info for the given queue. The base real
+ * address and number of entries of the defined queue are returned.
+ * The queue argument values are the same as for cpu_qconf() above.
+ *
+ * If the specified queue is a valid queue number, but no queue has
+ * been defined, the number of entries will be set to zero and the
+ * base real address returned is undefined.
+ */
+#define HV_FAST_CPU_QINFO 0x15
+
+/* cpu_mondo_send()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_MONDO_SEND
+ * ARG0-1: CPU list
+ * ARG2: data real address
+ * RET0: status
+ * ERRORS: EBADALIGN Mondo data is not 64-byte aligned or CPU list
+ * is not 2-byte aligned.
+ * ENORADDR Invalid data mondo address, or invalid cpu list
+ * address.
+ * ENOCPU Invalid cpu in CPU list
+ * EWOULDBLOCK Some or all of the listed CPUs did not receive
+ * the mondo
+ * ECPUERROR One or more of the listed CPUs are in error
+ * state, use HV_FAST_CPU_STATE to see which ones
+ * EINVAL CPU list includes caller's CPU ID
+ *
+ * Send a mondo interrupt to the CPUs in the given CPU list with the
+ * 64-bytes at the given data real address. The data must be 64-byte
+ * aligned. The mondo data will be delivered to the cpu_mondo queues
+ * of the recipient CPUs.
+ *
+ * In all cases, error or not, the CPUs in the CPU list to which the
+ * mondo has been successfully delivered will be indicated by having
+ * their entry in CPU list updated with the value 0xffff.
+ */
+#define HV_FAST_CPU_MONDO_SEND 0x42
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_cpu_mondo_send(unsigned long cpu_count,
+ unsigned long cpu_list_pa,
+ unsigned long mondo_block_pa);
+#endif
+
+/* cpu_myid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_MYID
+ * RET0: status
+ * RET1: CPU ID
+ * ERRORS: No errors defined.
+ *
+ * Return the hypervisor ID handle for the current CPU. Use by a
+ * virtual CPU to discover it's own identity.
+ */
+#define HV_FAST_CPU_MYID 0x16
+
+/* cpu_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_STATE
+ * ARG0: CPU ID
+ * RET0: status
+ * RET1: state
+ * ERRORS: ENOCPU Invalid CPU ID
+ *
+ * Retrieve the current state of the CPU with the given CPU ID.
+ */
+#define HV_FAST_CPU_STATE 0x17
+#define HV_CPU_STATE_STOPPED 0x01
+#define HV_CPU_STATE_RUNNING 0x02
+#define HV_CPU_STATE_ERROR 0x03
+
+#ifndef __ASSEMBLY__
+long sun4v_cpu_state(unsigned long cpuid);
+#endif
+
+/* cpu_set_rtba()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_SET_RTBA
+ * ARG0: RTBA
+ * RET0: status
+ * RET1: previous RTBA
+ * ERRORS: ENORADDR Invalid RTBA real address
+ * EBADALIGN RTBA is incorrectly aligned for a trap table
+ *
+ * Set the real trap base address of the local cpu to the given RTBA.
+ * The supplied RTBA must be aligned on a 256 byte boundary. Upon
+ * success the previous value of the RTBA is returned in RET1.
+ *
+ * Note: This service does not affect %tba
+ */
+#define HV_FAST_CPU_SET_RTBA 0x18
+
+/* cpu_set_rtba()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CPU_GET_RTBA
+ * RET0: status
+ * RET1: previous RTBA
+ * ERRORS: No possible error.
+ *
+ * Returns the current value of RTBA in RET1.
+ */
+#define HV_FAST_CPU_GET_RTBA 0x19
+
+/* MMU services.
+ *
+ * Layout of a TSB description for mmu_tsb_ctx{,non}0() calls.
+ */
+#ifndef __ASSEMBLY__
+struct hv_tsb_descr {
+ unsigned short pgsz_idx;
+ unsigned short assoc;
+ unsigned int num_ttes; /* in TTEs */
+ unsigned int ctx_idx;
+ unsigned int pgsz_mask;
+ unsigned long tsb_base;
+ unsigned long resv;
+};
+#endif
+#define HV_TSB_DESCR_PGSZ_IDX_OFFSET 0x00
+#define HV_TSB_DESCR_ASSOC_OFFSET 0x02
+#define HV_TSB_DESCR_NUM_TTES_OFFSET 0x04
+#define HV_TSB_DESCR_CTX_IDX_OFFSET 0x08
+#define HV_TSB_DESCR_PGSZ_MASK_OFFSET 0x0c
+#define HV_TSB_DESCR_TSB_BASE_OFFSET 0x10
+#define HV_TSB_DESCR_RESV_OFFSET 0x18
+
+/* Page size bitmask. */
+#define HV_PGSZ_MASK_8K (1 << 0)
+#define HV_PGSZ_MASK_64K (1 << 1)
+#define HV_PGSZ_MASK_512K (1 << 2)
+#define HV_PGSZ_MASK_4MB (1 << 3)
+#define HV_PGSZ_MASK_32MB (1 << 4)
+#define HV_PGSZ_MASK_256MB (1 << 5)
+#define HV_PGSZ_MASK_2GB (1 << 6)
+#define HV_PGSZ_MASK_16GB (1 << 7)
+
+/* Page size index. The value given in the TSB descriptor must correspond
+ * to the smallest page size specified in the pgsz_mask page size bitmask.
+ */
+#define HV_PGSZ_IDX_8K 0
+#define HV_PGSZ_IDX_64K 1
+#define HV_PGSZ_IDX_512K 2
+#define HV_PGSZ_IDX_4MB 3
+#define HV_PGSZ_IDX_32MB 4
+#define HV_PGSZ_IDX_256MB 5
+#define HV_PGSZ_IDX_2GB 6
+#define HV_PGSZ_IDX_16GB 7
+
+/* MMU fault status area.
+ *
+ * MMU related faults have their status and fault address information
+ * placed into a memory region made available by privileged code. Each
+ * virtual processor must make a mmu_fault_area_conf() call to tell the
+ * hypervisor where that processor's fault status should be stored.
+ *
+ * The fault status block is a multiple of 64-bytes and must be aligned
+ * on a 64-byte boundary.
+ */
+#ifndef __ASSEMBLY__
+struct hv_fault_status {
+ unsigned long i_fault_type;
+ unsigned long i_fault_addr;
+ unsigned long i_fault_ctx;
+ unsigned long i_reserved[5];
+ unsigned long d_fault_type;
+ unsigned long d_fault_addr;
+ unsigned long d_fault_ctx;
+ unsigned long d_reserved[5];
+};
+#endif
+#define HV_FAULT_I_TYPE_OFFSET 0x00
+#define HV_FAULT_I_ADDR_OFFSET 0x08
+#define HV_FAULT_I_CTX_OFFSET 0x10
+#define HV_FAULT_D_TYPE_OFFSET 0x40
+#define HV_FAULT_D_ADDR_OFFSET 0x48
+#define HV_FAULT_D_CTX_OFFSET 0x50
+
+#define HV_FAULT_TYPE_FAST_MISS 1
+#define HV_FAULT_TYPE_FAST_PROT 2
+#define HV_FAULT_TYPE_MMU_MISS 3
+#define HV_FAULT_TYPE_INV_RA 4
+#define HV_FAULT_TYPE_PRIV_VIOL 5
+#define HV_FAULT_TYPE_PROT_VIOL 6
+#define HV_FAULT_TYPE_NFO 7
+#define HV_FAULT_TYPE_NFO_SEFF 8
+#define HV_FAULT_TYPE_INV_VA 9
+#define HV_FAULT_TYPE_INV_ASI 10
+#define HV_FAULT_TYPE_NC_ATOMIC 11
+#define HV_FAULT_TYPE_PRIV_ACT 12
+#define HV_FAULT_TYPE_RESV1 13
+#define HV_FAULT_TYPE_UNALIGNED 14
+#define HV_FAULT_TYPE_INV_PGSZ 15
+#define HV_FAULT_TYPE_MCD 17
+#define HV_FAULT_TYPE_MCD_DIS 18
+/* Values 16 --> -2 are reserved. */
+#define HV_FAULT_TYPE_MULTIPLE -1
+
+/* Flags argument for mmu_{map,unmap}_addr(), mmu_demap_{page,context,all}(),
+ * and mmu_{map,unmap}_perm_addr().
+ */
+#define HV_MMU_DMMU 0x01
+#define HV_MMU_IMMU 0x02
+#define HV_MMU_ALL (HV_MMU_DMMU | HV_MMU_IMMU)
+
+/* mmu_map_addr()
+ * TRAP: HV_MMU_MAP_ADDR_TRAP
+ * ARG0: virtual address
+ * ARG1: mmu context
+ * ARG2: TTE
+ * ARG3: flags (HV_MMU_{IMMU,DMMU})
+ * ERRORS: EINVAL Invalid virtual address, mmu context, or flags
+ * EBADPGSZ Invalid page size value
+ * ENORADDR Invalid real address in TTE
+ *
+ * Create a non-permanent mapping using the given TTE, virtual
+ * address, and mmu context. The flags argument determines which
+ * (data, or instruction, or both) TLB the mapping gets loaded into.
+ *
+ * The behavior is undefined if the valid bit is clear in the TTE.
+ *
+ * Note: This API call is for privileged code to specify temporary translation
+ * mappings without the need to create and manage a TSB.
+ */
+
+/* mmu_unmap_addr()
+ * TRAP: HV_MMU_UNMAP_ADDR_TRAP
+ * ARG0: virtual address
+ * ARG1: mmu context
+ * ARG2: flags (HV_MMU_{IMMU,DMMU})
+ * ERRORS: EINVAL Invalid virtual address, mmu context, or flags
+ *
+ * Demaps the given virtual address in the given mmu context on this
+ * CPU. This function is intended to be used to demap pages mapped
+ * with mmu_map_addr. This service is equivalent to invoking
+ * mmu_demap_page() with only the current CPU in the CPU list. The
+ * flags argument determines which (data, or instruction, or both) TLB
+ * the mapping gets unmapped from.
+ *
+ * Attempting to perform an unmap operation for a previously defined
+ * permanent mapping will have undefined results.
+ */
+
+/* mmu_tsb_ctx0()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_TSB_CTX0
+ * ARG0: number of TSB descriptions
+ * ARG1: TSB descriptions pointer
+ * RET0: status
+ * ERRORS: ENORADDR Invalid TSB descriptions pointer or
+ * TSB base within a descriptor
+ * EBADALIGN TSB descriptions pointer is not aligned
+ * to an 8-byte boundary, or TSB base
+ * within a descriptor is not aligned for
+ * the given TSB size
+ * EBADPGSZ Invalid page size in a TSB descriptor
+ * EBADTSB Invalid associativity or size in a TSB
+ * descriptor
+ * EINVAL Invalid number of TSB descriptions, or
+ * invalid context index in a TSB
+ * descriptor, or index page size not
+ * equal to smallest page size in page
+ * size bitmask field.
+ *
+ * Configures the TSBs for the current CPU for virtual addresses with
+ * context zero. The TSB descriptions pointer is a pointer to an
+ * array of the given number of TSB descriptions.
+ *
+ * Note: The maximum number of TSBs available to a virtual CPU is given by the
+ * mmu-max-#tsbs property of the cpu's corresponding "cpu" node in the
+ * machine description.
+ */
+#define HV_FAST_MMU_TSB_CTX0 0x20
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mmu_tsb_ctx0(unsigned long num_descriptions,
+ unsigned long tsb_desc_ra);
+#endif
+
+/* mmu_tsb_ctxnon0()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_TSB_CTXNON0
+ * ARG0: number of TSB descriptions
+ * ARG1: TSB descriptions pointer
+ * RET0: status
+ * ERRORS: Same as for mmu_tsb_ctx0() above.
+ *
+ * Configures the TSBs for the current CPU for virtual addresses with
+ * non-zero contexts. The TSB descriptions pointer is a pointer to an
+ * array of the given number of TSB descriptions.
+ *
+ * Note: A maximum of 16 TSBs may be specified in the TSB description list.
+ */
+#define HV_FAST_MMU_TSB_CTXNON0 0x21
+
+/* mmu_demap_page()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_DEMAP_PAGE
+ * ARG0: reserved, must be zero
+ * ARG1: reserved, must be zero
+ * ARG2: virtual address
+ * ARG3: mmu context
+ * ARG4: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid virtual address, context, or
+ * flags value
+ * ENOTSUPPORTED ARG0 or ARG1 is non-zero
+ *
+ * Demaps any page mapping of the given virtual address in the given
+ * mmu context for the current virtual CPU. Any virtually tagged
+ * caches are guaranteed to be kept consistent. The flags argument
+ * determines which TLB (instruction, or data, or both) participate in
+ * the operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_PAGE 0x22
+
+/* mmu_demap_ctx()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_DEMAP_CTX
+ * ARG0: reserved, must be zero
+ * ARG1: reserved, must be zero
+ * ARG2: mmu context
+ * ARG3: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid context or flags value
+ * ENOTSUPPORTED ARG0 or ARG1 is non-zero
+ *
+ * Demaps all non-permanent virtual page mappings previously specified
+ * for the given context for the current virtual CPU. Any virtual
+ * tagged caches are guaranteed to be kept consistent. The flags
+ * argument determines which TLB (instruction, or data, or both)
+ * participate in the operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_CTX 0x23
+
+/* mmu_demap_all()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_DEMAP_ALL
+ * ARG0: reserved, must be zero
+ * ARG1: reserved, must be zero
+ * ARG2: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid flags value
+ * ENOTSUPPORTED ARG0 or ARG1 is non-zero
+ *
+ * Demaps all non-permanent virtual page mappings previously specified
+ * for the current virtual CPU. Any virtual tagged caches are
+ * guaranteed to be kept consistent. The flags argument determines
+ * which TLB (instruction, or data, or both) participate in the
+ * operation.
+ *
+ * ARG0 and ARG1 are both reserved and must be set to zero.
+ */
+#define HV_FAST_MMU_DEMAP_ALL 0x24
+
+#ifndef __ASSEMBLY__
+void sun4v_mmu_demap_all(void);
+#endif
+
+/* mmu_map_perm_addr()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_MAP_PERM_ADDR
+ * ARG0: virtual address
+ * ARG1: reserved, must be zero
+ * ARG2: TTE
+ * ARG3: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid virtual address or flags value
+ * EBADPGSZ Invalid page size value
+ * ENORADDR Invalid real address in TTE
+ * ETOOMANY Too many mappings (max of 8 reached)
+ *
+ * Create a permanent mapping using the given TTE and virtual address
+ * for context 0 on the calling virtual CPU. A maximum of 8 such
+ * permanent mappings may be specified by privileged code. Mappings
+ * may be removed with mmu_unmap_perm_addr().
+ *
+ * The behavior is undefined if a TTE with the valid bit clear is given.
+ *
+ * Note: This call is used to specify address space mappings for which
+ * privileged code does not expect to receive misses. For example,
+ * this mechanism can be used to map kernel nucleus code and data.
+ */
+#define HV_FAST_MMU_MAP_PERM_ADDR 0x25
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mmu_map_perm_addr(unsigned long vaddr,
+ unsigned long set_to_zero,
+ unsigned long tte,
+ unsigned long flags);
+#endif
+
+/* mmu_fault_area_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_FAULT_AREA_CONF
+ * ARG0: real address
+ * RET0: status
+ * RET1: previous mmu fault area real address
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Invalid alignment for fault area
+ *
+ * Configure the MMU fault status area for the calling CPU. A 64-byte
+ * aligned real address specifies where MMU fault status information
+ * is placed. The return value is the previously specified area, or 0
+ * for the first invocation. Specifying a fault area at real address
+ * 0 is not allowed.
+ */
+#define HV_FAST_MMU_FAULT_AREA_CONF 0x26
+
+/* mmu_enable()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_ENABLE
+ * ARG0: enable flag
+ * ARG1: return target address
+ * RET0: status
+ * ERRORS: ENORADDR Invalid real address when disabling
+ * translation.
+ * EBADALIGN The return target address is not
+ * aligned to an instruction.
+ * EINVAL The enable flag request the current
+ * operating mode (e.g. disable if already
+ * disabled)
+ *
+ * Enable or disable virtual address translation for the calling CPU
+ * within the virtual machine domain. If the enable flag is zero,
+ * translation is disabled, any non-zero value will enable
+ * translation.
+ *
+ * When this function returns, the newly selected translation mode
+ * will be active. If the mmu is being enabled, then the return
+ * target address is a virtual address else it is a real address.
+ *
+ * Upon successful completion, control will be returned to the given
+ * return target address (ie. the cpu will jump to that address). On
+ * failure, the previous mmu mode remains and the trap simply returns
+ * as normal with the appropriate error code in RET0.
+ */
+#define HV_FAST_MMU_ENABLE 0x27
+
+/* mmu_unmap_perm_addr()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_UNMAP_PERM_ADDR
+ * ARG0: virtual address
+ * ARG1: reserved, must be zero
+ * ARG2: flags (HV_MMU_{IMMU,DMMU})
+ * RET0: status
+ * ERRORS: EINVAL Invalid virtual address or flags value
+ * ENOMAP Specified mapping was not found
+ *
+ * Demaps any permanent page mapping (established via
+ * mmu_map_perm_addr()) at the given virtual address for context 0 on
+ * the current virtual CPU. Any virtual tagged caches are guaranteed
+ * to be kept consistent.
+ */
+#define HV_FAST_MMU_UNMAP_PERM_ADDR 0x28
+
+/* mmu_tsb_ctx0_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_TSB_CTX0_INFO
+ * ARG0: max TSBs
+ * ARG1: buffer pointer
+ * RET0: status
+ * RET1: number of TSBs
+ * ERRORS: EINVAL Supplied buffer is too small
+ * EBADALIGN The buffer pointer is badly aligned
+ * ENORADDR Invalid real address for buffer pointer
+ *
+ * Return the TSB configuration as previous defined by mmu_tsb_ctx0()
+ * into the provided buffer. The size of the buffer is given in ARG1
+ * in terms of the number of TSB description entries.
+ *
+ * Upon return, RET1 always contains the number of TSB descriptions
+ * previously configured. If zero TSBs were configured, EOK is
+ * returned with RET1 containing 0.
+ */
+#define HV_FAST_MMU_TSB_CTX0_INFO 0x29
+
+/* mmu_tsb_ctxnon0_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_TSB_CTXNON0_INFO
+ * ARG0: max TSBs
+ * ARG1: buffer pointer
+ * RET0: status
+ * RET1: number of TSBs
+ * ERRORS: EINVAL Supplied buffer is too small
+ * EBADALIGN The buffer pointer is badly aligned
+ * ENORADDR Invalid real address for buffer pointer
+ *
+ * Return the TSB configuration as previous defined by
+ * mmu_tsb_ctxnon0() into the provided buffer. The size of the buffer
+ * is given in ARG1 in terms of the number of TSB description entries.
+ *
+ * Upon return, RET1 always contains the number of TSB descriptions
+ * previously configured. If zero TSBs were configured, EOK is
+ * returned with RET1 containing 0.
+ */
+#define HV_FAST_MMU_TSB_CTXNON0_INFO 0x2a
+
+/* mmu_fault_area_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMU_FAULT_AREA_INFO
+ * RET0: status
+ * RET1: fault area real address
+ * ERRORS: No errors defined.
+ *
+ * Return the currently defined MMU fault status area for the current
+ * CPU. The real address of the fault status area is returned in
+ * RET1, or 0 is returned in RET1 if no fault status area is defined.
+ *
+ * Note: mmu_fault_area_conf() may be called with the return value (RET1)
+ * from this service if there is a need to save and restore the fault
+ * area for a cpu.
+ */
+#define HV_FAST_MMU_FAULT_AREA_INFO 0x2b
+
+/* Cache and Memory services. */
+
+/* mem_scrub()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MEM_SCRUB
+ * ARG0: real address
+ * ARG1: length
+ * RET0: status
+ * RET1: length scrubbed
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Start address or length are not correctly
+ * aligned
+ * EINVAL Length is zero
+ *
+ * Zero the memory contents in the range real address to real address
+ * plus length minus 1. Also, valid ECC will be generated for that
+ * memory address range. Scrubbing is started at the given real
+ * address, but may not scrub the entire given length. The actual
+ * length scrubbed will be returned in RET1.
+ *
+ * The real address and length must be aligned on an 8K boundary, or
+ * contain the start address and length from a sun4v error report.
+ *
+ * Note: There are two uses for this function. The first use is to block clear
+ * and initialize memory and the second is to scrub an u ncorrectable
+ * error reported via a resumable or non-resumable trap. The second
+ * use requires the arguments to be equal to the real address and length
+ * provided in a sun4v memory error report.
+ */
+#define HV_FAST_MEM_SCRUB 0x31
+
+/* mem_sync()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MEM_SYNC
+ * ARG0: real address
+ * ARG1: length
+ * RET0: status
+ * RET1: length synced
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Start address or length are not correctly
+ * aligned
+ * EINVAL Length is zero
+ *
+ * Force the next access within the real address to real address plus
+ * length minus 1 to be fetches from main system memory. Less than
+ * the given length may be synced, the actual amount synced is
+ * returned in RET1. The real address and length must be aligned on
+ * an 8K boundary.
+ */
+#define HV_FAST_MEM_SYNC 0x32
+
+/* Coprocessor services
+ *
+ * M7 and later processors provide an on-chip coprocessor which
+ * accelerates database operations, and is known internally as
+ * DAX.
+ */
+
+/* ccb_submit()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_CCB_SUBMIT
+ * ARG0: address of CCB array
+ * ARG1: size (in bytes) of CCB array being submitted
+ * ARG2: flags
+ * ARG3: reserved
+ * RET0: status (success or error code)
+ * RET1: size (in bytes) of CCB array that was accepted (might be less
+ * than arg1)
+ * RET2: status data
+ * if status == ENOMAP or ENOACCESS, identifies the VA in question
+ * if status == EUNAVAILBLE, unavailable code
+ * RET3: reserved
+ *
+ * ERRORS: EOK successful submission (check size)
+ * EWOULDBLOCK could not finish submissions, try again
+ * EBADALIGN array not 64B aligned or size not 64B multiple
+ * ENORADDR invalid RA for array or in CCB
+ * ENOMAP could not translate address (see status data)
+ * EINVAL invalid ccb or arguments
+ * ETOOMANY too many ccbs with all-or-nothing flag
+ * ENOACCESS guest has no access to submit ccbs or address
+ * in CCB does not have correct permissions (check
+ * status data)
+ * EUNAVAILABLE ccb operation could not be performed at this
+ * time (check status data)
+ * Status data codes:
+ * 0 - exact CCB could not be executed
+ * 1 - CCB opcode cannot be executed
+ * 2 - CCB version cannot be executed
+ * 3 - vcpu cannot execute CCBs
+ * 4 - no CCBs can be executed
+ */
+
+#define HV_CCB_SUBMIT 0x34
+#ifndef __ASSEMBLY__
+unsigned long sun4v_ccb_submit(unsigned long ccb_buf,
+ unsigned long len,
+ unsigned long flags,
+ unsigned long reserved,
+ void *submitted_len,
+ void *status_data);
+#endif
+
+/* flags (ARG2) */
+#define HV_CCB_QUERY_CMD BIT(1)
+#define HV_CCB_ARG0_TYPE_REAL 0UL
+#define HV_CCB_ARG0_TYPE_PRIMARY BIT(4)
+#define HV_CCB_ARG0_TYPE_SECONDARY BIT(5)
+#define HV_CCB_ARG0_TYPE_NUCLEUS GENMASK(5, 4)
+#define HV_CCB_ARG0_PRIVILEGED BIT(6)
+#define HV_CCB_ALL_OR_NOTHING BIT(7)
+#define HV_CCB_QUEUE_INFO BIT(8)
+#define HV_CCB_VA_REJECT 0UL
+#define HV_CCB_VA_SECONDARY BIT(13)
+#define HV_CCB_VA_NUCLEUS GENMASK(13, 12)
+#define HV_CCB_VA_PRIVILEGED BIT(14)
+#define HV_CCB_VA_READ_ADI_DISABLE BIT(15) /* DAX2 only */
+
+/* ccb_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_CCB_INFO
+ * ARG0: real address of CCB completion area
+ * RET0: status (success or error code)
+ * RET1: info array
+ * - RET1[0]: CCB state
+ * - RET1[1]: dax unit
+ * - RET1[2]: queue number
+ * - RET1[3]: queue position
+ *
+ * ERRORS: EOK operation successful
+ * EBADALIGN address not 64B aligned
+ * ENORADDR RA in address not valid
+ * EINVAL CA not valid
+ * EWOULDBLOCK info not available for this CCB currently, try
+ * again
+ * ENOACCESS guest cannot use dax
+ */
+
+#define HV_CCB_INFO 0x35
+#ifndef __ASSEMBLY__
+unsigned long sun4v_ccb_info(unsigned long ca,
+ void *info_arr);
+#endif
+
+/* info array byte offsets (RET1) */
+#define CCB_INFO_OFFSET_CCB_STATE 0
+#define CCB_INFO_OFFSET_DAX_UNIT 2
+#define CCB_INFO_OFFSET_QUEUE_NUM 4
+#define CCB_INFO_OFFSET_QUEUE_POS 6
+
+/* CCB state (RET1[0]) */
+#define HV_CCB_STATE_COMPLETED 0
+#define HV_CCB_STATE_ENQUEUED 1
+#define HV_CCB_STATE_INPROGRESS 2
+#define HV_CCB_STATE_NOTFOUND 3
+
+/* ccb_kill()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_CCB_KILL
+ * ARG0: real address of CCB completion area
+ * RET0: status (success or error code)
+ * RET1: CCB kill status
+ *
+ * ERRORS: EOK operation successful
+ * EBADALIGN address not 64B aligned
+ * ENORADDR RA in address not valid
+ * EINVAL CA not valid
+ * EWOULDBLOCK kill not available for this CCB currently, try
+ * again
+ * ENOACCESS guest cannot use dax
+ */
+
+#define HV_CCB_KILL 0x36
+#ifndef __ASSEMBLY__
+unsigned long sun4v_ccb_kill(unsigned long ca,
+ void *kill_status);
+#endif
+
+/* CCB kill status (RET1) */
+#define HV_CCB_KILL_COMPLETED 0
+#define HV_CCB_KILL_DEQUEUED 1
+#define HV_CCB_KILL_KILLED 2
+#define HV_CCB_KILL_NOTFOUND 3
+
+/* Time of day services.
+ *
+ * The hypervisor maintains the time of day on a per-domain basis.
+ * Changing the time of day in one domain does not affect the time of
+ * day on any other domain.
+ *
+ * Time is described by a single unsigned 64-bit word which is the
+ * number of seconds since the UNIX Epoch (00:00:00 UTC, January 1,
+ * 1970).
+ */
+
+/* tod_get()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TOD_GET
+ * RET0: status
+ * RET1: TOD
+ * ERRORS: EWOULDBLOCK TOD resource is temporarily unavailable
+ * ENOTSUPPORTED If TOD not supported on this platform
+ *
+ * Return the current time of day. May block if TOD access is
+ * temporarily not possible.
+ */
+#define HV_FAST_TOD_GET 0x50
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_tod_get(unsigned long *time);
+#endif
+
+/* tod_set()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TOD_SET
+ * ARG0: TOD
+ * RET0: status
+ * ERRORS: EWOULDBLOCK TOD resource is temporarily unavailable
+ * ENOTSUPPORTED If TOD not supported on this platform
+ *
+ * The current time of day is set to the value specified in ARG0. May
+ * block if TOD access is temporarily not possible.
+ */
+#define HV_FAST_TOD_SET 0x51
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_tod_set(unsigned long time);
+#endif
+
+/* Console services */
+
+/* con_getchar()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CONS_GETCHAR
+ * RET0: status
+ * RET1: character
+ * ERRORS: EWOULDBLOCK No character available.
+ *
+ * Returns a character from the console device. If no character is
+ * available then an EWOULDBLOCK error is returned. If a character is
+ * available, then the returned status is EOK and the character value
+ * is in RET1.
+ *
+ * A virtual BREAK is represented by the 64-bit value -1.
+ *
+ * A virtual HUP signal is represented by the 64-bit value -2.
+ */
+#define HV_FAST_CONS_GETCHAR 0x60
+
+/* con_putchar()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CONS_PUTCHAR
+ * ARG0: character
+ * RET0: status
+ * ERRORS: EINVAL Illegal character
+ * EWOULDBLOCK Output buffer currently full, would block
+ *
+ * Send a character to the console device. Only character values
+ * between 0 and 255 may be used. Values outside this range are
+ * invalid except for the 64-bit value -1 which is used to send a
+ * virtual BREAK.
+ */
+#define HV_FAST_CONS_PUTCHAR 0x61
+
+/* con_read()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CONS_READ
+ * ARG0: buffer real address
+ * ARG1: buffer size in bytes
+ * RET0: status
+ * RET1: bytes read or BREAK or HUP
+ * ERRORS: EWOULDBLOCK No character available.
+ *
+ * Reads characters into a buffer from the console device. If no
+ * character is available then an EWOULDBLOCK error is returned.
+ * If a character is available, then the returned status is EOK
+ * and the number of bytes read into the given buffer is provided
+ * in RET1.
+ *
+ * A virtual BREAK is represented by the 64-bit RET1 value -1.
+ *
+ * A virtual HUP signal is represented by the 64-bit RET1 value -2.
+ *
+ * If BREAK or HUP are indicated, no bytes were read into buffer.
+ */
+#define HV_FAST_CONS_READ 0x62
+
+/* con_write()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_CONS_WRITE
+ * ARG0: buffer real address
+ * ARG1: buffer size in bytes
+ * RET0: status
+ * RET1: bytes written
+ * ERRORS: EWOULDBLOCK Output buffer currently full, would block
+ *
+ * Send a characters in buffer to the console device. Breaks must be
+ * sent using con_putchar().
+ */
+#define HV_FAST_CONS_WRITE 0x63
+
+#ifndef __ASSEMBLY__
+long sun4v_con_getchar(long *status);
+long sun4v_con_putchar(long c);
+long sun4v_con_read(unsigned long buffer,
+ unsigned long size,
+ unsigned long *bytes_read);
+unsigned long sun4v_con_write(unsigned long buffer,
+ unsigned long size,
+ unsigned long *bytes_written);
+#endif
+
+/* mach_set_soft_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_SET_SOFT_STATE
+ * ARG0: software state
+ * ARG1: software state description pointer
+ * RET0: status
+ * ERRORS: EINVAL software state not valid or software state
+ * description is not NULL terminated
+ * ENORADDR software state description pointer is not a
+ * valid real address
+ * EBADALIGNED software state description is not correctly
+ * aligned
+ *
+ * This allows the guest to report it's soft state to the hypervisor. There
+ * are two primary components to this state. The first part states whether
+ * the guest software is running or not. The second containts optional
+ * details specific to the software.
+ *
+ * The software state argument is defined below in HV_SOFT_STATE_*, and
+ * indicates whether the guest is operating normally or in a transitional
+ * state.
+ *
+ * The software state description argument is a real address of a data buffer
+ * of size 32-bytes aligned on a 32-byte boundary. It is treated as a NULL
+ * terminated 7-bit ASCII string of up to 31 characters not including the
+ * NULL termination.
+ */
+#define HV_FAST_MACH_SET_SOFT_STATE 0x70
+#define HV_SOFT_STATE_NORMAL 0x01
+#define HV_SOFT_STATE_TRANSITION 0x02
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mach_set_soft_state(unsigned long soft_state,
+ unsigned long msg_string_ra);
+#endif
+
+/* mach_get_soft_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MACH_GET_SOFT_STATE
+ * ARG0: software state description pointer
+ * RET0: status
+ * RET1: software state
+ * ERRORS: ENORADDR software state description pointer is not a
+ * valid real address
+ * EBADALIGNED software state description is not correctly
+ * aligned
+ *
+ * Retrieve the current value of the guest's software state. The rules
+ * for the software state pointer are the same as for mach_set_soft_state()
+ * above.
+ */
+#define HV_FAST_MACH_GET_SOFT_STATE 0x71
+
+/* svc_send()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_SEND
+ * ARG0: service ID
+ * ARG1: buffer real address
+ * ARG2: buffer size
+ * RET0: STATUS
+ * RET1: sent_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_SEND 0x80
+
+/* svc_recv()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_RECV
+ * ARG0: service ID
+ * ARG1: buffer real address
+ * ARG2: buffer size
+ * RET0: STATUS
+ * RET1: recv_bytes
+ *
+ * Be careful, all output registers are clobbered by this operation,
+ * so for example it is not possible to save away a value in %o4
+ * across the trap.
+ */
+#define HV_FAST_SVC_RECV 0x81
+
+/* svc_getstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_GETSTATUS
+ * ARG0: service ID
+ * RET0: STATUS
+ * RET1: status bits
+ */
+#define HV_FAST_SVC_GETSTATUS 0x82
+
+/* svc_setstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_SETSTATUS
+ * ARG0: service ID
+ * ARG1: bits to set
+ * RET0: STATUS
+ */
+#define HV_FAST_SVC_SETSTATUS 0x83
+
+/* svc_clrstatus()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SVC_CLRSTATUS
+ * ARG0: service ID
+ * ARG1: bits to clear
+ * RET0: STATUS
+ */
+#define HV_FAST_SVC_CLRSTATUS 0x84
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_svc_send(unsigned long svc_id,
+ unsigned long buffer,
+ unsigned long buffer_size,
+ unsigned long *sent_bytes);
+unsigned long sun4v_svc_recv(unsigned long svc_id,
+ unsigned long buffer,
+ unsigned long buffer_size,
+ unsigned long *recv_bytes);
+unsigned long sun4v_svc_getstatus(unsigned long svc_id,
+ unsigned long *status_bits);
+unsigned long sun4v_svc_setstatus(unsigned long svc_id,
+ unsigned long status_bits);
+unsigned long sun4v_svc_clrstatus(unsigned long svc_id,
+ unsigned long status_bits);
+#endif
+
+/* Trap trace services.
+ *
+ * The hypervisor provides a trap tracing capability for privileged
+ * code running on each virtual CPU. Privileged code provides a
+ * round-robin trap trace queue within which the hypervisor writes
+ * 64-byte entries detailing hyperprivileged traps taken n behalf of
+ * privileged code. This is provided as a debugging capability for
+ * privileged code.
+ *
+ * The trap trace control structure is 64-bytes long and placed at the
+ * start (offset 0) of the trap trace buffer, and is described as
+ * follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_trap_trace_control {
+ unsigned long head_offset;
+ unsigned long tail_offset;
+ unsigned long __reserved[0x30 / sizeof(unsigned long)];
+};
+#endif
+#define HV_TRAP_TRACE_CTRL_HEAD_OFFSET 0x00
+#define HV_TRAP_TRACE_CTRL_TAIL_OFFSET 0x08
+
+/* The head offset is the offset of the most recently completed entry
+ * in the trap-trace buffer. The tail offset is the offset of the
+ * next entry to be written. The control structure is owned and
+ * modified by the hypervisor. A guest may not modify the control
+ * structure contents. Attempts to do so will result in undefined
+ * behavior for the guest.
+ *
+ * Each trap trace buffer entry is laid out as follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_trap_trace_entry {
+ unsigned char type; /* Hypervisor or guest entry? */
+ unsigned char hpstate; /* Hyper-privileged state */
+ unsigned char tl; /* Trap level */
+ unsigned char gl; /* Global register level */
+ unsigned short tt; /* Trap type */
+ unsigned short tag; /* Extended trap identifier */
+ unsigned long tstate; /* Trap state */
+ unsigned long tick; /* Tick */
+ unsigned long tpc; /* Trap PC */
+ unsigned long f1; /* Entry specific */
+ unsigned long f2; /* Entry specific */
+ unsigned long f3; /* Entry specific */
+ unsigned long f4; /* Entry specific */
+};
+#endif
+#define HV_TRAP_TRACE_ENTRY_TYPE 0x00
+#define HV_TRAP_TRACE_ENTRY_HPSTATE 0x01
+#define HV_TRAP_TRACE_ENTRY_TL 0x02
+#define HV_TRAP_TRACE_ENTRY_GL 0x03
+#define HV_TRAP_TRACE_ENTRY_TT 0x04
+#define HV_TRAP_TRACE_ENTRY_TAG 0x06
+#define HV_TRAP_TRACE_ENTRY_TSTATE 0x08
+#define HV_TRAP_TRACE_ENTRY_TICK 0x10
+#define HV_TRAP_TRACE_ENTRY_TPC 0x18
+#define HV_TRAP_TRACE_ENTRY_F1 0x20
+#define HV_TRAP_TRACE_ENTRY_F2 0x28
+#define HV_TRAP_TRACE_ENTRY_F3 0x30
+#define HV_TRAP_TRACE_ENTRY_F4 0x38
+
+/* The type field is encoded as follows. */
+#define HV_TRAP_TYPE_UNDEF 0x00 /* Entry content undefined */
+#define HV_TRAP_TYPE_HV 0x01 /* Hypervisor trap entry */
+#define HV_TRAP_TYPE_GUEST 0xff /* Added via ttrace_addentry() */
+
+/* ttrace_buf_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TTRACE_BUF_CONF
+ * ARG0: real address
+ * ARG1: number of entries
+ * RET0: status
+ * RET1: number of entries
+ * ERRORS: ENORADDR Invalid real address
+ * EINVAL Size is too small
+ * EBADALIGN Real address not aligned on 64-byte boundary
+ *
+ * Requests hypervisor trap tracing and declares a virtual CPU's trap
+ * trace buffer to the hypervisor. The real address supplies the real
+ * base address of the trap trace queue and must be 64-byte aligned.
+ * Specifying a value of 0 for the number of entries disables trap
+ * tracing for the calling virtual CPU. The buffer allocated must be
+ * sized for a power of two number of 64-byte trap trace entries plus
+ * an initial 64-byte control structure.
+ *
+ * This may be invoked any number of times so that a virtual CPU may
+ * relocate a trap trace buffer or create "snapshots" of information.
+ *
+ * If the real address is illegal or badly aligned, then trap tracing
+ * is disabled and an error is returned.
+ *
+ * Upon failure with EINVAL, this service call returns in RET1 the
+ * minimum number of buffer entries required. Upon other failures
+ * RET1 is undefined.
+ */
+#define HV_FAST_TTRACE_BUF_CONF 0x90
+
+/* ttrace_buf_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TTRACE_BUF_INFO
+ * RET0: status
+ * RET1: real address
+ * RET2: size
+ * ERRORS: None defined.
+ *
+ * Returns the size and location of the previously declared trap-trace
+ * buffer. In the event that no buffer was previously defined, or the
+ * buffer is disabled, this call will return a size of zero bytes.
+ */
+#define HV_FAST_TTRACE_BUF_INFO 0x91
+
+/* ttrace_enable()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TTRACE_ENABLE
+ * ARG0: enable
+ * RET0: status
+ * RET1: previous enable state
+ * ERRORS: EINVAL No trap trace buffer currently defined
+ *
+ * Enable or disable trap tracing, and return the previous enabled
+ * state in RET1. Future systems may define various flags for the
+ * enable argument (ARG0), for the moment a guest should pass
+ * "(uint64_t) -1" to enable, and "(uint64_t) 0" to disable all
+ * tracing - which will ensure future compatibility.
+ */
+#define HV_FAST_TTRACE_ENABLE 0x92
+
+/* ttrace_freeze()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_TTRACE_FREEZE
+ * ARG0: freeze
+ * RET0: status
+ * RET1: previous freeze state
+ * ERRORS: EINVAL No trap trace buffer currently defined
+ *
+ * Freeze or unfreeze trap tracing, returning the previous freeze
+ * state in RET1. A guest should pass a non-zero value to freeze and
+ * a zero value to unfreeze all tracing. The returned previous state
+ * is 0 for not frozen and 1 for frozen.
+ */
+#define HV_FAST_TTRACE_FREEZE 0x93
+
+/* ttrace_addentry()
+ * TRAP: HV_TTRACE_ADDENTRY_TRAP
+ * ARG0: tag (16-bits)
+ * ARG1: data word 0
+ * ARG2: data word 1
+ * ARG3: data word 2
+ * ARG4: data word 3
+ * RET0: status
+ * ERRORS: EINVAL No trap trace buffer currently defined
+ *
+ * Add an entry to the trap trace buffer. Upon return only ARG0/RET0
+ * is modified - none of the other registers holding arguments are
+ * volatile across this hypervisor service.
+ */
+
+/* Core dump services.
+ *
+ * Since the hypervisor viraulizes and thus obscures a lot of the
+ * physical machine layout and state, traditional OS crash dumps can
+ * be difficult to diagnose especially when the problem is a
+ * configuration error of some sort.
+ *
+ * The dump services provide an opaque buffer into which the
+ * hypervisor can place it's internal state in order to assist in
+ * debugging such situations. The contents are opaque and extremely
+ * platform and hypervisor implementation specific. The guest, during
+ * a core dump, requests that the hypervisor update any information in
+ * the dump buffer in preparation to being dumped as part of the
+ * domain's memory image.
+ */
+
+/* dump_buf_update()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_DUMP_BUF_UPDATE
+ * ARG0: real address
+ * ARG1: size
+ * RET0: status
+ * RET1: required size of dump buffer
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Real address is not aligned on a 64-byte
+ * boundary
+ * EINVAL Size is non-zero but less than minimum size
+ * required
+ * ENOTSUPPORTED Operation not supported on current logical
+ * domain
+ *
+ * Declare a domain dump buffer to the hypervisor. The real address
+ * provided for the domain dump buffer must be 64-byte aligned. The
+ * size specifies the size of the dump buffer and may be larger than
+ * the minimum size specified in the machine description. The
+ * hypervisor will fill the dump buffer with opaque data.
+ *
+ * Note: A guest may elect to include dump buffer contents as part of a crash
+ * dump to assist with debugging. This function may be called any number
+ * of times so that a guest may relocate a dump buffer, or create
+ * "snapshots" of any dump-buffer information. Each call to
+ * dump_buf_update() atomically declares the new dump buffer to the
+ * hypervisor.
+ *
+ * A specified size of 0 unconfigures the dump buffer. If the real
+ * address is illegal or badly aligned, then any currently active dump
+ * buffer is disabled and an error is returned.
+ *
+ * In the event that the call fails with EINVAL, RET1 contains the
+ * minimum size requires by the hypervisor for a valid dump buffer.
+ */
+#define HV_FAST_DUMP_BUF_UPDATE 0x94
+
+/* dump_buf_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_DUMP_BUF_INFO
+ * RET0: status
+ * RET1: real address of current dump buffer
+ * RET2: size of current dump buffer
+ * ERRORS: No errors defined.
+ *
+ * Return the currently configures dump buffer description. A
+ * returned size of 0 bytes indicates an undefined dump buffer. In
+ * this case the return address in RET1 is undefined.
+ */
+#define HV_FAST_DUMP_BUF_INFO 0x95
+
+/* Device interrupt services.
+ *
+ * Device interrupts are allocated to system bus bridges by the hypervisor,
+ * and described to OBP in the machine description. OBP then describes
+ * these interrupts to the OS via properties in the device tree.
+ *
+ * Terminology:
+ *
+ * cpuid Unique opaque value which represents a target cpu.
+ *
+ * devhandle Device handle. It uniquely identifies a device, and
+ * consistes of the lower 28-bits of the hi-cell of the
+ * first entry of the device's "reg" property in the
+ * OBP device tree.
+ *
+ * devino Device interrupt number. Specifies the relative
+ * interrupt number within the device. The unique
+ * combination of devhandle and devino are used to
+ * identify a specific device interrupt.
+ *
+ * Note: The devino value is the same as the values in the
+ * "interrupts" property or "interrupt-map" property
+ * in the OBP device tree for that device.
+ *
+ * sysino System interrupt number. A 64-bit unsigned interger
+ * representing a unique interrupt within a virtual
+ * machine.
+ *
+ * intr_state A flag representing the interrupt state for a given
+ * sysino. The state values are defined below.
+ *
+ * intr_enabled A flag representing the 'enabled' state for a given
+ * sysino. The enable values are defined below.
+ */
+
+#define HV_INTR_STATE_IDLE 0 /* Nothing pending */
+#define HV_INTR_STATE_RECEIVED 1 /* Interrupt received by hardware */
+#define HV_INTR_STATE_DELIVERED 2 /* Interrupt delivered to queue */
+
+#define HV_INTR_DISABLED 0 /* sysino not enabled */
+#define HV_INTR_ENABLED 1 /* sysino enabled */
+
+/* intr_devino_to_sysino()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_DEVINO2SYSINO
+ * ARG0: devhandle
+ * ARG1: devino
+ * RET0: status
+ * RET1: sysino
+ * ERRORS: EINVAL Invalid devhandle/devino
+ *
+ * Converts a device specific interrupt number of the given
+ * devhandle/devino into a system specific ino (sysino).
+ */
+#define HV_FAST_INTR_DEVINO2SYSINO 0xa0
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_devino_to_sysino(unsigned long devhandle,
+ unsigned long devino);
+#endif
+
+/* intr_getenabled()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_GETENABLED
+ * ARG0: sysino
+ * RET0: status
+ * RET1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
+ * ERRORS: EINVAL Invalid sysino
+ *
+ * Returns interrupt enabled state in RET1 for the interrupt defined
+ * by the given sysino.
+ */
+#define HV_FAST_INTR_GETENABLED 0xa1
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_getenabled(unsigned long sysino);
+#endif
+
+/* intr_setenabled()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_SETENABLED
+ * ARG0: sysino
+ * ARG1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
+ * RET0: status
+ * ERRORS: EINVAL Invalid sysino or intr_enabled value
+ *
+ * Set the 'enabled' state of the interrupt sysino.
+ */
+#define HV_FAST_INTR_SETENABLED 0xa2
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_setenabled(unsigned long sysino,
+ unsigned long intr_enabled);
+#endif
+
+/* intr_getstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_GETSTATE
+ * ARG0: sysino
+ * RET0: status
+ * RET1: intr_state (HV_INTR_STATE_*)
+ * ERRORS: EINVAL Invalid sysino
+ *
+ * Returns current state of the interrupt defined by the given sysino.
+ */
+#define HV_FAST_INTR_GETSTATE 0xa3
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_getstate(unsigned long sysino);
+#endif
+
+/* intr_setstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_SETSTATE
+ * ARG0: sysino
+ * ARG1: intr_state (HV_INTR_STATE_*)
+ * RET0: status
+ * ERRORS: EINVAL Invalid sysino or intr_state value
+ *
+ * Sets the current state of the interrupt described by the given sysino
+ * value.
+ *
+ * Note: Setting the state to HV_INTR_STATE_IDLE clears any pending
+ * interrupt for sysino.
+ */
+#define HV_FAST_INTR_SETSTATE 0xa4
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_setstate(unsigned long sysino, unsigned long intr_state);
+#endif
+
+/* intr_gettarget()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_GETTARGET
+ * ARG0: sysino
+ * RET0: status
+ * RET1: cpuid
+ * ERRORS: EINVAL Invalid sysino
+ *
+ * Returns CPU that is the current target of the interrupt defined by
+ * the given sysino. The CPU value returned is undefined if the target
+ * has not been set via intr_settarget().
+ */
+#define HV_FAST_INTR_GETTARGET 0xa5
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_gettarget(unsigned long sysino);
+#endif
+
+/* intr_settarget()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_INTR_SETTARGET
+ * ARG0: sysino
+ * ARG1: cpuid
+ * RET0: status
+ * ERRORS: EINVAL Invalid sysino
+ * ENOCPU Invalid cpuid
+ *
+ * Set the target CPU for the interrupt defined by the given sysino.
+ */
+#define HV_FAST_INTR_SETTARGET 0xa6
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_intr_settarget(unsigned long sysino, unsigned long cpuid);
+#endif
+
+/* vintr_get_cookie()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_GET_COOKIE
+ * ARG0: device handle
+ * ARG1: device ino
+ * RET0: status
+ * RET1: cookie
+ */
+#define HV_FAST_VINTR_GET_COOKIE 0xa7
+
+/* vintr_set_cookie()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_SET_COOKIE
+ * ARG0: device handle
+ * ARG1: device ino
+ * ARG2: cookie
+ * RET0: status
+ */
+#define HV_FAST_VINTR_SET_COOKIE 0xa8
+
+/* vintr_get_valid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_GET_VALID
+ * ARG0: device handle
+ * ARG1: device ino
+ * RET0: status
+ * RET1: valid state
+ */
+#define HV_FAST_VINTR_GET_VALID 0xa9
+
+/* vintr_set_valid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_SET_VALID
+ * ARG0: device handle
+ * ARG1: device ino
+ * ARG2: valid state
+ * RET0: status
+ */
+#define HV_FAST_VINTR_SET_VALID 0xaa
+
+/* vintr_get_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_GET_STATE
+ * ARG0: device handle
+ * ARG1: device ino
+ * RET0: status
+ * RET1: state
+ */
+#define HV_FAST_VINTR_GET_STATE 0xab
+
+/* vintr_set_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_SET_STATE
+ * ARG0: device handle
+ * ARG1: device ino
+ * ARG2: state
+ * RET0: status
+ */
+#define HV_FAST_VINTR_SET_STATE 0xac
+
+/* vintr_get_target()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_GET_TARGET
+ * ARG0: device handle
+ * ARG1: device ino
+ * RET0: status
+ * RET1: cpuid
+ */
+#define HV_FAST_VINTR_GET_TARGET 0xad
+
+/* vintr_set_target()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_VINTR_SET_TARGET
+ * ARG0: device handle
+ * ARG1: device ino
+ * ARG2: cpuid
+ * RET0: status
+ */
+#define HV_FAST_VINTR_SET_TARGET 0xae
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_vintr_get_cookie(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long *cookie);
+unsigned long sun4v_vintr_set_cookie(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long cookie);
+unsigned long sun4v_vintr_get_valid(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long *valid);
+unsigned long sun4v_vintr_set_valid(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long valid);
+unsigned long sun4v_vintr_get_state(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long *state);
+unsigned long sun4v_vintr_set_state(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long state);
+unsigned long sun4v_vintr_get_target(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long *cpuid);
+unsigned long sun4v_vintr_set_target(unsigned long dev_handle,
+ unsigned long dev_ino,
+ unsigned long cpuid);
+#endif
+
+/* PCI IO services.
+ *
+ * See the terminology descriptions in the device interrupt services
+ * section above as those apply here too. Here are terminology
+ * definitions specific to these PCI IO services:
+ *
+ * tsbnum TSB number. Indentifies which io-tsb is used.
+ * For this version of the specification, tsbnum
+ * must be zero.
+ *
+ * tsbindex TSB index. Identifies which entry in the TSB
+ * is used. The first entry is zero.
+ *
+ * tsbid A 64-bit aligned data structure which contains
+ * a tsbnum and a tsbindex. Bits 63:32 contain the
+ * tsbnum and bits 31:00 contain the tsbindex.
+ *
+ * Use the HV_PCI_TSBID() macro to construct such
+ * values.
+ *
+ * io_attributes IO attributes for IOMMU mappings. One of more
+ * of the attritbute bits are stores in a 64-bit
+ * value. The values are defined below.
+ *
+ * r_addr 64-bit real address
+ *
+ * pci_device PCI device address. A PCI device address identifies
+ * a specific device on a specific PCI bus segment.
+ * A PCI device address ia a 32-bit unsigned integer
+ * with the following format:
+ *
+ * 00000000.bbbbbbbb.dddddfff.00000000
+ *
+ * Use the HV_PCI_DEVICE_BUILD() macro to construct
+ * such values.
+ *
+ * pci_config_offset
+ * PCI configureation space offset. For conventional
+ * PCI a value between 0 and 255. For extended
+ * configuration space, a value between 0 and 4095.
+ *
+ * Note: For PCI configuration space accesses, the offset
+ * must be aligned to the access size.
+ *
+ * error_flag A return value which specifies if the action succeeded
+ * or failed. 0 means no error, non-0 means some error
+ * occurred while performing the service.
+ *
+ * io_sync_direction
+ * Direction definition for pci_dma_sync(), defined
+ * below in HV_PCI_SYNC_*.
+ *
+ * io_page_list A list of io_page_addresses, an io_page_address is
+ * a real address.
+ *
+ * io_page_list_p A pointer to an io_page_list.
+ *
+ * "size based byte swap" - Some functions do size based byte swapping
+ * which allows sw to access pointers and
+ * counters in native form when the processor
+ * operates in a different endianness than the
+ * IO bus. Size-based byte swapping converts a
+ * multi-byte field between big-endian and
+ * little-endian format.
+ */
+
+#define HV_PCI_MAP_ATTR_READ 0x01
+#define HV_PCI_MAP_ATTR_WRITE 0x02
+#define HV_PCI_MAP_ATTR_RELAXED_ORDER 0x04
+
+#define HV_PCI_DEVICE_BUILD(b,d,f) \
+ ((((b) & 0xff) << 16) | \
+ (((d) & 0x1f) << 11) | \
+ (((f) & 0x07) << 8))
+
+#define HV_PCI_TSBID(__tsb_num, __tsb_index) \
+ ((((u64)(__tsb_num)) << 32UL) | ((u64)(__tsb_index)))
+
+#define HV_PCI_SYNC_FOR_DEVICE 0x01
+#define HV_PCI_SYNC_FOR_CPU 0x02
+
+/* pci_iommu_map()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOMMU_MAP
+ * ARG0: devhandle
+ * ARG1: tsbid
+ * ARG2: #ttes
+ * ARG3: io_attributes
+ * ARG4: io_page_list_p
+ * RET0: status
+ * RET1: #ttes mapped
+ * ERRORS: EINVAL Invalid devhandle/tsbnum/tsbindex/io_attributes
+ * EBADALIGN Improperly aligned real address
+ * ENORADDR Invalid real address
+ *
+ * Create IOMMU mappings in the sun4v device defined by the given
+ * devhandle. The mappings are created in the TSB defined by the
+ * tsbnum component of the given tsbid. The first mapping is created
+ * in the TSB i ndex defined by the tsbindex component of the given tsbid.
+ * The call creates up to #ttes mappings, the first one at tsbnum, tsbindex,
+ * the second at tsbnum, tsbindex + 1, etc.
+ *
+ * All mappings are created with the attributes defined by the io_attributes
+ * argument. The page mapping addresses are described in the io_page_list
+ * defined by the given io_page_list_p, which is a pointer to the io_page_list.
+ * The first entry in the io_page_list is the address for the first iotte, the
+ * 2nd for the 2nd iotte, and so on.
+ *
+ * Each io_page_address in the io_page_list must be appropriately aligned.
+ * #ttes must be greater than zero. For this version of the spec, the tsbnum
+ * component of the given tsbid must be zero.
+ *
+ * Returns the actual number of mappings creates, which may be less than
+ * or equal to the argument #ttes. If the function returns a value which
+ * is less than the #ttes, the caller may continus to call the function with
+ * an updated tsbid, #ttes, io_page_list_p arguments until all pages are
+ * mapped.
+ *
+ * Note: This function does not imply an iotte cache flush. The guest must
+ * demap an entry before re-mapping it.
+ */
+#define HV_FAST_PCI_IOMMU_MAP 0xb0
+
+/* pci_iommu_demap()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOMMU_DEMAP
+ * ARG0: devhandle
+ * ARG1: tsbid
+ * ARG2: #ttes
+ * RET0: status
+ * RET1: #ttes demapped
+ * ERRORS: EINVAL Invalid devhandle/tsbnum/tsbindex
+ *
+ * Demap and flush IOMMU mappings in the device defined by the given
+ * devhandle. Demaps up to #ttes entries in the TSB defined by the tsbnum
+ * component of the given tsbid, starting at the TSB index defined by the
+ * tsbindex component of the given tsbid.
+ *
+ * For this version of the spec, the tsbnum of the given tsbid must be zero.
+ * #ttes must be greater than zero.
+ *
+ * Returns the actual number of ttes demapped, which may be less than or equal
+ * to the argument #ttes. If #ttes demapped is less than #ttes, the caller
+ * may continue to call this function with updated tsbid and #ttes arguments
+ * until all pages are demapped.
+ *
+ * Note: Entries do not have to be mapped to be demapped. A demap of an
+ * unmapped page will flush the entry from the tte cache.
+ */
+#define HV_FAST_PCI_IOMMU_DEMAP 0xb1
+
+/* pci_iommu_getmap()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOMMU_GETMAP
+ * ARG0: devhandle
+ * ARG1: tsbid
+ * RET0: status
+ * RET1: io_attributes
+ * RET2: real address
+ * ERRORS: EINVAL Invalid devhandle/tsbnum/tsbindex
+ * ENOMAP Mapping is not valid, no translation exists
+ *
+ * Read and return the mapping in the device described by the given devhandle
+ * and tsbid. If successful, the io_attributes shall be returned in RET1
+ * and the page address of the mapping shall be returned in RET2.
+ *
+ * For this version of the spec, the tsbnum component of the given tsbid
+ * must be zero.
+ */
+#define HV_FAST_PCI_IOMMU_GETMAP 0xb2
+
+/* pci_iommu_getbypass()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOMMU_GETBYPASS
+ * ARG0: devhandle
+ * ARG1: real address
+ * ARG2: io_attributes
+ * RET0: status
+ * RET1: io_addr
+ * ERRORS: EINVAL Invalid devhandle/io_attributes
+ * ENORADDR Invalid real address
+ * ENOTSUPPORTED Function not supported in this implementation.
+ *
+ * Create a "special" mapping in the device described by the given devhandle,
+ * for the given real address and attributes. Return the IO address in RET1
+ * if successful.
+ */
+#define HV_FAST_PCI_IOMMU_GETBYPASS 0xb3
+
+/* pci_config_get()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_CONFIG_GET
+ * ARG0: devhandle
+ * ARG1: pci_device
+ * ARG2: pci_config_offset
+ * ARG3: size
+ * RET0: status
+ * RET1: error_flag
+ * RET2: data
+ * ERRORS: EINVAL Invalid devhandle/pci_device/offset/size
+ * EBADALIGN pci_config_offset not size aligned
+ * ENOACCESS Access to this offset is not permitted
+ *
+ * Read PCI configuration space for the adapter described by the given
+ * devhandle. Read size (1, 2, or 4) bytes of data from the given
+ * pci_device, at pci_config_offset from the beginning of the device's
+ * configuration space. If there was no error, RET1 is set to zero and
+ * RET2 is set to the data read. Insignificant bits in RET2 are not
+ * guaranteed to have any specific value and therefore must be ignored.
+ *
+ * The data returned in RET2 is size based byte swapped.
+ *
+ * If an error occurs during the read, set RET1 to a non-zero value. The
+ * given pci_config_offset must be 'size' aligned.
+ */
+#define HV_FAST_PCI_CONFIG_GET 0xb4
+
+/* pci_config_put()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_CONFIG_PUT
+ * ARG0: devhandle
+ * ARG1: pci_device
+ * ARG2: pci_config_offset
+ * ARG3: size
+ * ARG4: data
+ * RET0: status
+ * RET1: error_flag
+ * ERRORS: EINVAL Invalid devhandle/pci_device/offset/size
+ * EBADALIGN pci_config_offset not size aligned
+ * ENOACCESS Access to this offset is not permitted
+ *
+ * Write PCI configuration space for the adapter described by the given
+ * devhandle. Write size (1, 2, or 4) bytes of data in a single operation,
+ * at pci_config_offset from the beginning of the device's configuration
+ * space. The data argument contains the data to be written to configuration
+ * space. Prior to writing, the data is size based byte swapped.
+ *
+ * If an error occurs during the write access, do not generate an error
+ * report, do set RET1 to a non-zero value. Otherwise RET1 is zero.
+ * The given pci_config_offset must be 'size' aligned.
+ *
+ * This function is permitted to read from offset zero in the configuration
+ * space described by the given pci_device if necessary to ensure that the
+ * write access to config space completes.
+ */
+#define HV_FAST_PCI_CONFIG_PUT 0xb5
+
+/* pci_peek()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_PEEK
+ * ARG0: devhandle
+ * ARG1: real address
+ * ARG2: size
+ * RET0: status
+ * RET1: error_flag
+ * RET2: data
+ * ERRORS: EINVAL Invalid devhandle or size
+ * EBADALIGN Improperly aligned real address
+ * ENORADDR Bad real address
+ * ENOACCESS Guest access prohibited
+ *
+ * Attempt to read the IO address given by the given devhandle, real address,
+ * and size. Size must be 1, 2, 4, or 8. The read is performed as a single
+ * access operation using the given size. If an error occurs when reading
+ * from the given location, do not generate an error report, but return a
+ * non-zero value in RET1. If the read was successful, return zero in RET1
+ * and return the actual data read in RET2. The data returned is size based
+ * byte swapped.
+ *
+ * Non-significant bits in RET2 are not guaranteed to have any specific value
+ * and therefore must be ignored. If RET1 is returned as non-zero, the data
+ * value is not guaranteed to have any specific value and should be ignored.
+ *
+ * The caller must have permission to read from the given devhandle, real
+ * address, which must be an IO address. The argument real address must be a
+ * size aligned address.
+ *
+ * The hypervisor implementation of this function must block access to any
+ * IO address that the guest does not have explicit permission to access.
+ */
+#define HV_FAST_PCI_PEEK 0xb6
+
+/* pci_poke()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_POKE
+ * ARG0: devhandle
+ * ARG1: real address
+ * ARG2: size
+ * ARG3: data
+ * ARG4: pci_device
+ * RET0: status
+ * RET1: error_flag
+ * ERRORS: EINVAL Invalid devhandle, size, or pci_device
+ * EBADALIGN Improperly aligned real address
+ * ENORADDR Bad real address
+ * ENOACCESS Guest access prohibited
+ * ENOTSUPPORTED Function is not supported by implementation
+ *
+ * Attempt to write data to the IO address given by the given devhandle,
+ * real address, and size. Size must be 1, 2, 4, or 8. The write is
+ * performed as a single access operation using the given size. Prior to
+ * writing the data is size based swapped.
+ *
+ * If an error occurs when writing to the given location, do not generate an
+ * error report, but return a non-zero value in RET1. If the write was
+ * successful, return zero in RET1.
+ *
+ * pci_device describes the configuration address of the device being
+ * written to. The implementation may safely read from offset 0 with
+ * the configuration space of the device described by devhandle and
+ * pci_device in order to guarantee that the write portion of the operation
+ * completes
+ *
+ * Any error that occurs due to the read shall be reported using the normal
+ * error reporting mechanisms .. the read error is not suppressed.
+ *
+ * The caller must have permission to write to the given devhandle, real
+ * address, which must be an IO address. The argument real address must be a
+ * size aligned address. The caller must have permission to read from
+ * the given devhandle, pci_device cofiguration space offset 0.
+ *
+ * The hypervisor implementation of this function must block access to any
+ * IO address that the guest does not have explicit permission to access.
+ */
+#define HV_FAST_PCI_POKE 0xb7
+
+/* pci_dma_sync()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_DMA_SYNC
+ * ARG0: devhandle
+ * ARG1: real address
+ * ARG2: size
+ * ARG3: io_sync_direction
+ * RET0: status
+ * RET1: #synced
+ * ERRORS: EINVAL Invalid devhandle or io_sync_direction
+ * ENORADDR Bad real address
+ *
+ * Synchronize a memory region described by the given real address and size,
+ * for the device defined by the given devhandle using the direction(s)
+ * defined by the given io_sync_direction. The argument size is the size of
+ * the memory region in bytes.
+ *
+ * Return the actual number of bytes synchronized in the return value #synced,
+ * which may be less than or equal to the argument size. If the return
+ * value #synced is less than size, the caller must continue to call this
+ * function with updated real address and size arguments until the entire
+ * memory region is synchronized.
+ */
+#define HV_FAST_PCI_DMA_SYNC 0xb8
+
+/* PCI MSI services. */
+
+#define HV_MSITYPE_MSI32 0x00
+#define HV_MSITYPE_MSI64 0x01
+
+#define HV_MSIQSTATE_IDLE 0x00
+#define HV_MSIQSTATE_ERROR 0x01
+
+#define HV_MSIQ_INVALID 0x00
+#define HV_MSIQ_VALID 0x01
+
+#define HV_MSISTATE_IDLE 0x00
+#define HV_MSISTATE_DELIVERED 0x01
+
+#define HV_MSIVALID_INVALID 0x00
+#define HV_MSIVALID_VALID 0x01
+
+#define HV_PCIE_MSGTYPE_PME_MSG 0x18
+#define HV_PCIE_MSGTYPE_PME_ACK_MSG 0x1b
+#define HV_PCIE_MSGTYPE_CORR_MSG 0x30
+#define HV_PCIE_MSGTYPE_NONFATAL_MSG 0x31
+#define HV_PCIE_MSGTYPE_FATAL_MSG 0x33
+
+#define HV_MSG_INVALID 0x00
+#define HV_MSG_VALID 0x01
+
+/* pci_msiq_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_CONF
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * ARG2: real address
+ * ARG3: number of entries
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle, msiqid or nentries
+ * EBADALIGN Improperly aligned real address
+ * ENORADDR Bad real address
+ *
+ * Configure the MSI queue given by the devhandle and msiqid arguments,
+ * and to be placed at the given real address and be of the given
+ * number of entries. The real address must be aligned exactly to match
+ * the queue size. Each queue entry is 64-bytes long, so f.e. a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary. The MSI-EQ
+ * Head and Tail are initialized so that the MSI-EQ is 'empty'.
+ *
+ * Implementation Note: Certain implementations have fixed sized queues. In
+ * that case, number of entries must contain the correct
+ * value.
+ */
+#define HV_FAST_PCI_MSIQ_CONF 0xc0
+
+/* pci_msiq_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_INFO
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: real address
+ * RET2: number of entries
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Return the configuration information for the MSI queue described
+ * by the given devhandle and msiqid. The base address of the queue
+ * is returned in ARG1 and the number of entries is returned in ARG2.
+ * If the queue is unconfigured, the real address is undefined and the
+ * number of entries will be returned as zero.
+ */
+#define HV_FAST_PCI_MSIQ_INFO 0xc1
+
+/* pci_msiq_getvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETVALID
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: msiqvalid (HV_MSIQ_VALID or HV_MSIQ_INVALID)
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Get the valid state of the MSI-EQ described by the given devhandle and
+ * msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETVALID 0xc2
+
+/* pci_msiq_setvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_SETVALID
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * ARG2: msiqvalid (HV_MSIQ_VALID or HV_MSIQ_INVALID)
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msiqid or msiqvalid
+ * value or MSI EQ is uninitialized
+ *
+ * Set the valid state of the MSI-EQ described by the given devhandle and
+ * msiqid to the given msiqvalid.
+ */
+#define HV_FAST_PCI_MSIQ_SETVALID 0xc3
+
+/* pci_msiq_getstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETSTATE
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: msiqstate (HV_MSIQSTATE_IDLE or HV_MSIQSTATE_ERROR)
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Get the state of the MSI-EQ described by the given devhandle and
+ * msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETSTATE 0xc4
+
+/* pci_msiq_getvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETVALID
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * ARG2: msiqstate (HV_MSIQSTATE_IDLE or HV_MSIQSTATE_ERROR)
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msiqid or msiqstate
+ * value or MSI EQ is uninitialized
+ *
+ * Set the state of the MSI-EQ described by the given devhandle and
+ * msiqid to the given msiqvalid.
+ */
+#define HV_FAST_PCI_MSIQ_SETSTATE 0xc5
+
+/* pci_msiq_gethead()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETHEAD
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: msiqhead
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Get the current MSI EQ queue head for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETHEAD 0xc6
+
+/* pci_msiq_sethead()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_SETHEAD
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * ARG2: msiqhead
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msiqid or msiqhead,
+ * or MSI EQ is uninitialized
+ *
+ * Set the current MSI EQ queue head for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_SETHEAD 0xc7
+
+/* pci_msiq_gettail()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSIQ_GETTAIL
+ * ARG0: devhandle
+ * ARG1: msiqid
+ * RET0: status
+ * RET1: msiqtail
+ * ERRORS: EINVAL Invalid devhandle or msiqid
+ *
+ * Get the current MSI EQ queue tail for the MSI-EQ described by the
+ * given devhandle and msiqid.
+ */
+#define HV_FAST_PCI_MSIQ_GETTAIL 0xc8
+
+/* pci_msi_getvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_GETVALID
+ * ARG0: devhandle
+ * ARG1: msinum
+ * RET0: status
+ * RET1: msivalidstate
+ * ERRORS: EINVAL Invalid devhandle or msinum
+ *
+ * Get the current valid/enabled state for the MSI defined by the
+ * given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_GETVALID 0xc9
+
+/* pci_msi_setvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_SETVALID
+ * ARG0: devhandle
+ * ARG1: msinum
+ * ARG2: msivalidstate
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msinum or msivalidstate
+ *
+ * Set the current valid/enabled state for the MSI defined by the
+ * given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_SETVALID 0xca
+
+/* pci_msi_getmsiq()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_GETMSIQ
+ * ARG0: devhandle
+ * ARG1: msinum
+ * RET0: status
+ * RET1: msiqid
+ * ERRORS: EINVAL Invalid devhandle or msinum or MSI is unbound
+ *
+ * Get the MSI EQ that the MSI defined by the given devhandle and
+ * msinum is bound to.
+ */
+#define HV_FAST_PCI_MSI_GETMSIQ 0xcb
+
+/* pci_msi_setmsiq()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_SETMSIQ
+ * ARG0: devhandle
+ * ARG1: msinum
+ * ARG2: msitype
+ * ARG3: msiqid
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msinum or msiqid
+ *
+ * Set the MSI EQ that the MSI defined by the given devhandle and
+ * msinum is bound to.
+ */
+#define HV_FAST_PCI_MSI_SETMSIQ 0xcc
+
+/* pci_msi_getstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_GETSTATE
+ * ARG0: devhandle
+ * ARG1: msinum
+ * RET0: status
+ * RET1: msistate
+ * ERRORS: EINVAL Invalid devhandle or msinum
+ *
+ * Get the state of the MSI defined by the given devhandle and msinum.
+ * If not initialized, return HV_MSISTATE_IDLE.
+ */
+#define HV_FAST_PCI_MSI_GETSTATE 0xcd
+
+/* pci_msi_setstate()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSI_SETSTATE
+ * ARG0: devhandle
+ * ARG1: msinum
+ * ARG2: msistate
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msinum or msistate
+ *
+ * Set the state of the MSI defined by the given devhandle and msinum.
+ */
+#define HV_FAST_PCI_MSI_SETSTATE 0xce
+
+/* pci_msg_getmsiq()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSG_GETMSIQ
+ * ARG0: devhandle
+ * ARG1: msgtype
+ * RET0: status
+ * RET1: msiqid
+ * ERRORS: EINVAL Invalid devhandle or msgtype
+ *
+ * Get the MSI EQ of the MSG defined by the given devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_GETMSIQ 0xd0
+
+/* pci_msg_setmsiq()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSG_SETMSIQ
+ * ARG0: devhandle
+ * ARG1: msgtype
+ * ARG2: msiqid
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle, msgtype, or msiqid
+ *
+ * Set the MSI EQ of the MSG defined by the given devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_SETMSIQ 0xd1
+
+/* pci_msg_getvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSG_GETVALID
+ * ARG0: devhandle
+ * ARG1: msgtype
+ * RET0: status
+ * RET1: msgvalidstate
+ * ERRORS: EINVAL Invalid devhandle or msgtype
+ *
+ * Get the valid/enabled state of the MSG defined by the given
+ * devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_GETVALID 0xd2
+
+/* pci_msg_setvalid()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_MSG_SETVALID
+ * ARG0: devhandle
+ * ARG1: msgtype
+ * ARG2: msgvalidstate
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or msgtype or msgvalidstate
+ *
+ * Set the valid/enabled state of the MSG defined by the given
+ * devhandle and msgtype.
+ */
+#define HV_FAST_PCI_MSG_SETVALID 0xd3
+
+/* PCI IOMMU v2 definitions and services
+ *
+ * While the PCI IO definitions above is valid IOMMU v2 adds new PCI IO
+ * definitions and services.
+ *
+ * CTE Clump Table Entry. First level table entry in the ATU.
+ *
+ * pci_device_list
+ * A 32-bit aligned list of pci_devices.
+ *
+ * pci_device_listp
+ * real address of a pci_device_list. 32-bit aligned.
+ *
+ * iotte IOMMU translation table entry.
+ *
+ * iotte_attributes
+ * IO Attributes for IOMMU v2 mappings. In addition to
+ * read, write IOMMU v2 supports relax ordering
+ *
+ * io_page_list A 64-bit aligned list of real addresses. Each real
+ * address in an io_page_list must be properly aligned
+ * to the pagesize of the given IOTSB.
+ *
+ * io_page_list_p Real address of an io_page_list, 64-bit aligned.
+ *
+ * IOTSB IO Translation Storage Buffer. An aligned table of
+ * IOTTEs. Each IOTSB has a pagesize, table size, and
+ * virtual address associated with it that must match
+ * a pagesize and table size supported by the un-derlying
+ * hardware implementation. The alignment requirements
+ * for an IOTSB depend on the pagesize used for that IOTSB.
+ * Each IOTTE in an IOTSB maps one pagesize-sized page.
+ * The size of the IOTSB dictates how large of a virtual
+ * address space the IOTSB is capable of mapping.
+ *
+ * iotsb_handle An opaque identifier for an IOTSB. A devhandle plus
+ * iotsb_handle represents a binding of an IOTSB to a
+ * PCI root complex.
+ *
+ * iotsb_index Zero-based IOTTE number within an IOTSB.
+ */
+
+/* The index_count argument consists of two fields:
+ * bits 63:48 #iottes and bits 47:0 iotsb_index
+ */
+#define HV_PCI_IOTSB_INDEX_COUNT(__iottes, __iotsb_index) \
+ (((u64)(__iottes) << 48UL) | ((u64)(__iotsb_index)))
+
+/* pci_iotsb_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_CONF
+ * ARG0: devhandle
+ * ARG1: r_addr
+ * ARG2: size
+ * ARG3: pagesize
+ * ARG4: iova
+ * RET0: status
+ * RET1: iotsb_handle
+ * ERRORS: EINVAL Invalid devhandle, size, iova, or pagesize
+ * EBADALIGN r_addr is not properly aligned
+ * ENORADDR r_addr is not a valid real address
+ * ETOOMANY No further IOTSBs may be configured
+ * EBUSY Duplicate devhandle, raddir, iova combination
+ *
+ * Create an IOTSB suitable for the PCI root complex identified by devhandle,
+ * for the DMA virtual address defined by the argument iova.
+ *
+ * r_addr is the properly aligned base address of the IOTSB and size is the
+ * IOTSB (table) size in bytes.The IOTSB is required to be zeroed prior to
+ * being configured. If it contains any values other than zeros then the
+ * behavior is undefined.
+ *
+ * pagesize is the size of each page in the IOTSB. Note that the combination of
+ * size (table size) and pagesize must be valid.
+ *
+ * virt is the DMA virtual address this IOTSB will map.
+ *
+ * If successful, the opaque 64-bit handle iotsb_handle is returned in ret1.
+ * Once configured, privileged access to the IOTSB memory is prohibited and
+ * creates undefined behavior. The only permitted access is indirect via these
+ * services.
+ */
+#define HV_FAST_PCI_IOTSB_CONF 0x190
+
+/* pci_iotsb_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_INFO
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * RET0: status
+ * RET1: r_addr
+ * RET2: size
+ * RET3: pagesize
+ * RET4: iova
+ * RET5: #bound
+ * ERRORS: EINVAL Invalid devhandle or iotsb_handle
+ *
+ * This service returns configuration information about an IOTSB previously
+ * created with pci_iotsb_conf.
+ *
+ * iotsb_handle value 0 may be used with this service to inquire about the
+ * legacy IOTSB that may or may not exist. If the service succeeds, the return
+ * values describe the legacy IOTSB and I/O virtual addresses mapped by that
+ * table. However, the table base address r_addr may contain the value -1 which
+ * indicates a memory range that cannot be accessed or be reclaimed.
+ *
+ * The return value #bound contains the number of PCI devices that iotsb_handle
+ * is currently bound to.
+ */
+#define HV_FAST_PCI_IOTSB_INFO 0x191
+
+/* pci_iotsb_unconf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_UNCONF
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle or iotsb_handle
+ * EBUSY The IOTSB is bound and may not be unconfigured
+ *
+ * This service unconfigures the IOTSB identified by the devhandle and
+ * iotsb_handle arguments, previously created with pci_iotsb_conf.
+ * The IOTSB must not be currently bound to any device or the service will fail
+ *
+ * If the call succeeds, iotsb_handle is no longer valid.
+ */
+#define HV_FAST_PCI_IOTSB_UNCONF 0x192
+
+/* pci_iotsb_bind()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_BIND
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * ARG2: pci_device
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle, iotsb_handle, or pci_device
+ * EBUSY A PCI function is already bound to an IOTSB at the same
+ * address range as specified by devhandle, iotsb_handle.
+ *
+ * This service binds the PCI function specified by the argument pci_device to
+ * the IOTSB specified by the arguments devhandle and iotsb_handle.
+ *
+ * The PCI device function is bound to the specified IOTSB with the IOVA range
+ * specified when the IOTSB was configured via pci_iotsb_conf. If the function
+ * is already bound then it is unbound first.
+ */
+#define HV_FAST_PCI_IOTSB_BIND 0x193
+
+/* pci_iotsb_unbind()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_UNBIND
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * ARG2: pci_device
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle, iotsb_handle, or pci_device
+ * ENOMAP The PCI function was not bound to the specified IOTSB
+ *
+ * This service unbinds the PCI device specified by the argument pci_device
+ * from the IOTSB identified * by the arguments devhandle and iotsb_handle.
+ *
+ * If the PCI device is not bound to the specified IOTSB then this service will
+ * fail with status ENOMAP
+ */
+#define HV_FAST_PCI_IOTSB_UNBIND 0x194
+
+/* pci_iotsb_get_binding()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_GET_BINDING
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * ARG2: iova
+ * RET0: status
+ * RET1: iotsb_handle
+ * ERRORS: EINVAL Invalid devhandle, pci_device, or iova
+ * ENOMAP The PCI function is not bound to an IOTSB at iova
+ *
+ * This service returns the IOTSB binding, iotsb_handle, for a given pci_device
+ * and DMA virtual address, iova.
+ *
+ * iova must be the base address of a DMA virtual address range as defined by
+ * the iommu-address-ranges property in the root complex device node defined
+ * by the argument devhandle.
+ */
+#define HV_FAST_PCI_IOTSB_GET_BINDING 0x195
+
+/* pci_iotsb_map()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_MAP
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * ARG2: index_count
+ * ARG3: iotte_attributes
+ * ARG4: io_page_list_p
+ * RET0: status
+ * RET1: #mapped
+ * ERRORS: EINVAL Invalid devhandle, iotsb_handle, #iottes,
+ * iotsb_index or iotte_attributes
+ * EBADALIGN Improperly aligned io_page_list_p or I/O page
+ * address in the I/O page list.
+ * ENORADDR Invalid io_page_list_p or I/O page address in
+ * the I/O page list.
+ *
+ * This service creates and flushes mappings in the IOTSB defined by the
+ * arguments devhandle, iotsb.
+ *
+ * The index_count argument consists of two fields. Bits 63:48 contain #iotte
+ * and bits 47:0 contain iotsb_index
+ *
+ * The first mapping is created in the IOTSB index specified by iotsb_index.
+ * Subsequent mappings are created at iotsb_index+1 and so on.
+ *
+ * The attributes of each mapping are defined by the argument iotte_attributes.
+ *
+ * The io_page_list_p specifies the real address of the 64-bit-aligned list of
+ * #iottes I/O page addresses. Each page address must be a properly aligned
+ * real address of a page to be mapped in the IOTSB. The first entry in the I/O
+ * page list contains the real address of the first page, the 2nd entry for the
+ * 2nd page, and so on.
+ *
+ * #iottes must be greater than zero.
+ *
+ * The return value #mapped is the actual number of mappings created, which may
+ * be less than or equal to the argument #iottes. If the function returns
+ * successfully with a #mapped value less than the requested #iottes then the
+ * caller should continue to invoke the service with updated iotsb_index,
+ * #iottes, and io_page_list_p arguments until all pages are mapped.
+ *
+ * This service must not be used to demap a mapping. In other words, all
+ * mappings must be valid and have one or both of the RW attribute bits set.
+ *
+ * Note:
+ * It is implementation-defined whether I/O page real address validity checking
+ * is done at time mappings are established or deferred until they are
+ * accessed.
+ */
+#define HV_FAST_PCI_IOTSB_MAP 0x196
+
+/* pci_iotsb_map_one()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_MAP_ONE
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * ARG2: iotsb_index
+ * ARG3: iotte_attributes
+ * ARG4: r_addr
+ * RET0: status
+ * ERRORS: EINVAL Invalid devhandle,iotsb_handle, iotsb_index
+ * or iotte_attributes
+ * EBADALIGN Improperly aligned r_addr
+ * ENORADDR Invalid r_addr
+ *
+ * This service creates and flushes a single mapping in the IOTSB defined by the
+ * arguments devhandle, iotsb.
+ *
+ * The mapping for the page at r_addr is created at the IOTSB index specified by
+ * iotsb_index with the attributes iotte_attributes.
+ *
+ * This service must not be used to demap a mapping. In other words, the mapping
+ * must be valid and have one or both of the RW attribute bits set.
+ *
+ * Note:
+ * It is implementation-defined whether I/O page real address validity checking
+ * is done at time mappings are established or deferred until they are
+ * accessed.
+ */
+#define HV_FAST_PCI_IOTSB_MAP_ONE 0x197
+
+/* pci_iotsb_demap()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_DEMAP
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * ARG2: iotsb_index
+ * ARG3: #iottes
+ * RET0: status
+ * RET1: #unmapped
+ * ERRORS: EINVAL Invalid devhandle, iotsb_handle, iotsb_index or #iottes
+ *
+ * This service unmaps and flushes up to #iottes mappings starting at index
+ * iotsb_index from the IOTSB defined by the arguments devhandle, iotsb.
+ *
+ * #iottes must be greater than zero.
+ *
+ * The actual number of IOTTEs unmapped is returned in #unmapped and may be less
+ * than or equal to the requested number of IOTTEs, #iottes.
+ *
+ * If #unmapped is less than #iottes, the caller should continue to invoke this
+ * service with updated iotsb_index and #iottes arguments until all pages are
+ * demapped.
+ */
+#define HV_FAST_PCI_IOTSB_DEMAP 0x198
+
+/* pci_iotsb_getmap()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_GETMAP
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * ARG2: iotsb_index
+ * RET0: status
+ * RET1: r_addr
+ * RET2: iotte_attributes
+ * ERRORS: EINVAL Invalid devhandle, iotsb_handle, or iotsb_index
+ * ENOMAP No mapping was found
+ *
+ * This service returns the mapping specified by index iotsb_index from the
+ * IOTSB defined by the arguments devhandle, iotsb.
+ *
+ * Upon success, the real address of the mapping shall be returned in
+ * r_addr and thethe IOTTE mapping attributes shall be returned in
+ * iotte_attributes.
+ *
+ * The return value iotte_attributes may not include optional features used in
+ * the call to create the mapping.
+ */
+#define HV_FAST_PCI_IOTSB_GETMAP 0x199
+
+/* pci_iotsb_sync_mappings()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_PCI_IOTSB_SYNC_MAPPINGS
+ * ARG0: devhandle
+ * ARG1: iotsb_handle
+ * ARG2: iotsb_index
+ * ARG3: #iottes
+ * RET0: status
+ * RET1: #synced
+ * ERROS: EINVAL Invalid devhandle, iotsb_handle, iotsb_index, or #iottes
+ *
+ * This service synchronizes #iottes mappings starting at index iotsb_index in
+ * the IOTSB defined by the arguments devhandle, iotsb.
+ *
+ * #iottes must be greater than zero.
+ *
+ * The actual number of IOTTEs synchronized is returned in #synced, which may
+ * be less than or equal to the requested number, #iottes.
+ *
+ * Upon a successful return, #synced is less than #iottes, the caller should
+ * continue to invoke this service with updated iotsb_index and #iottes
+ * arguments until all pages are synchronized.
+ */
+#define HV_FAST_PCI_IOTSB_SYNC_MAPPINGS 0x19a
+
+/* Logical Domain Channel services. */
+
+#define LDC_CHANNEL_DOWN 0
+#define LDC_CHANNEL_UP 1
+#define LDC_CHANNEL_RESETTING 2
+
+/* ldc_tx_qconf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_TX_QCONF
+ * ARG0: channel ID
+ * ARG1: real address base of queue
+ * ARG2: num entries in queue
+ * RET0: status
+ *
+ * Configure transmit queue for the LDC endpoint specified by the
+ * given channel ID, to be placed at the given real address, and
+ * be of the given num entries. Num entries must be a power of two.
+ * The real address base of the queue must be aligned on the queue
+ * size. Each queue entry is 64-bytes, so for example, a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.
+ *
+ * Upon configuration of a valid transmit queue the head and tail
+ * pointers are set to a hypervisor specific identical value indicating
+ * that the queue initially is empty.
+ *
+ * The endpoint's transmit queue is un-configured if num entries is zero.
+ *
+ * The maximum number of entries for each queue for a specific cpu may be
+ * determined from the machine description. A transmit queue may be
+ * specified even in the event that the LDC is down (peer endpoint has no
+ * receive queue specified). Transmission will begin as soon as the peer
+ * endpoint defines a receive queue.
+ *
+ * It is recommended that a guest wait for a transmit queue to empty prior
+ * to reconfiguring it, or un-configuring it. Re or un-configuring of a
+ * non-empty transmit queue behaves exactly as defined above, however it
+ * is undefined as to how many of the pending entries in the original queue
+ * will be delivered prior to the re-configuration taking effect.
+ * Furthermore, as the queue configuration causes a reset of the head and
+ * tail pointers there is no way for a guest to determine how many entries
+ * have been sent after the configuration operation.
+ */
+#define HV_FAST_LDC_TX_QCONF 0xe0
+
+/* ldc_tx_qinfo()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_TX_QINFO
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: real address base of queue
+ * RET2: num entries in queue
+ *
+ * Return the configuration info for the transmit queue of LDC endpoint
+ * defined by the given channel ID. The real address is the currently
+ * defined real address base of the defined queue, and num entries is the
+ * size of the queue in terms of number of entries.
+ *
+ * If the specified channel ID is a valid endpoint number, but no transmit
+ * queue has been defined this service will return success, but with num
+ * entries set to zero and the real address will have an undefined value.
+ */
+#define HV_FAST_LDC_TX_QINFO 0xe1
+
+/* ldc_tx_get_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_TX_GET_STATE
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: head offset
+ * RET2: tail offset
+ * RET3: channel state
+ *
+ * Return the transmit state, and the head and tail queue pointers, for
+ * the transmit queue of the LDC endpoint defined by the given channel ID.
+ * The head and tail values are the byte offset of the head and tail
+ * positions of the transmit queue for the specified endpoint.
+ */
+#define HV_FAST_LDC_TX_GET_STATE 0xe2
+
+/* ldc_tx_set_qtail()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_TX_SET_QTAIL
+ * ARG0: channel ID
+ * ARG1: tail offset
+ * RET0: status
+ *
+ * Update the tail pointer for the transmit queue associated with the LDC
+ * endpoint defined by the given channel ID. The tail offset specified
+ * must be aligned on a 64 byte boundary, and calculated so as to increase
+ * the number of pending entries on the transmit queue. Any attempt to
+ * decrease the number of pending transmit queue entires is considered
+ * an invalid tail offset and will result in an EINVAL error.
+ *
+ * Since the tail of the transmit queue may not be moved backwards, the
+ * transmit queue may be flushed by configuring a new transmit queue,
+ * whereupon the hypervisor will configure the initial transmit head and
+ * tail pointers to be equal.
+ */
+#define HV_FAST_LDC_TX_SET_QTAIL 0xe3
+
+/* ldc_rx_qconf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_RX_QCONF
+ * ARG0: channel ID
+ * ARG1: real address base of queue
+ * ARG2: num entries in queue
+ * RET0: status
+ *
+ * Configure receive queue for the LDC endpoint specified by the
+ * given channel ID, to be placed at the given real address, and
+ * be of the given num entries. Num entries must be a power of two.
+ * The real address base of the queue must be aligned on the queue
+ * size. Each queue entry is 64-bytes, so for example, a 32 entry
+ * queue must be aligned on a 2048 byte real address boundary.
+ *
+ * The endpoint's transmit queue is un-configured if num entries is zero.
+ *
+ * If a valid receive queue is specified for a local endpoint the LDC is
+ * in the up state for the purpose of transmission to this endpoint.
+ *
+ * The maximum number of entries for each queue for a specific cpu may be
+ * determined from the machine description.
+ *
+ * As receive queue configuration causes a reset of the queue's head and
+ * tail pointers there is no way for a gues to determine how many entries
+ * have been received between a preceding ldc_get_rx_state() API call
+ * and the completion of the configuration operation. It should be noted
+ * that datagram delivery is not guaranteed via domain channels anyway,
+ * and therefore any higher protocol should be resilient to datagram
+ * loss if necessary. However, to overcome this specific race potential
+ * it is recommended, for example, that a higher level protocol be employed
+ * to ensure either retransmission, or ensure that no datagrams are pending
+ * on the peer endpoint's transmit queue prior to the configuration process.
+ */
+#define HV_FAST_LDC_RX_QCONF 0xe4
+
+/* ldc_rx_qinfo()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_RX_QINFO
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: real address base of queue
+ * RET2: num entries in queue
+ *
+ * Return the configuration info for the receive queue of LDC endpoint
+ * defined by the given channel ID. The real address is the currently
+ * defined real address base of the defined queue, and num entries is the
+ * size of the queue in terms of number of entries.
+ *
+ * If the specified channel ID is a valid endpoint number, but no receive
+ * queue has been defined this service will return success, but with num
+ * entries set to zero and the real address will have an undefined value.
+ */
+#define HV_FAST_LDC_RX_QINFO 0xe5
+
+/* ldc_rx_get_state()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_RX_GET_STATE
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: head offset
+ * RET2: tail offset
+ * RET3: channel state
+ *
+ * Return the receive state, and the head and tail queue pointers, for
+ * the receive queue of the LDC endpoint defined by the given channel ID.
+ * The head and tail values are the byte offset of the head and tail
+ * positions of the receive queue for the specified endpoint.
+ */
+#define HV_FAST_LDC_RX_GET_STATE 0xe6
+
+/* ldc_rx_set_qhead()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_RX_SET_QHEAD
+ * ARG0: channel ID
+ * ARG1: head offset
+ * RET0: status
+ *
+ * Update the head pointer for the receive queue associated with the LDC
+ * endpoint defined by the given channel ID. The head offset specified
+ * must be aligned on a 64 byte boundary, and calculated so as to decrease
+ * the number of pending entries on the receive queue. Any attempt to
+ * increase the number of pending receive queue entires is considered
+ * an invalid head offset and will result in an EINVAL error.
+ *
+ * The receive queue may be flushed by setting the head offset equal
+ * to the current tail offset.
+ */
+#define HV_FAST_LDC_RX_SET_QHEAD 0xe7
+
+/* LDC Map Table Entry. Each slot is defined by a translation table
+ * entry, as specified by the LDC_MTE_* bits below, and a 64-bit
+ * hypervisor invalidation cookie.
+ */
+#define LDC_MTE_PADDR 0x0fffffffffffe000 /* pa[55:13] */
+#define LDC_MTE_COPY_W 0x0000000000000400 /* copy write access */
+#define LDC_MTE_COPY_R 0x0000000000000200 /* copy read access */
+#define LDC_MTE_IOMMU_W 0x0000000000000100 /* IOMMU write access */
+#define LDC_MTE_IOMMU_R 0x0000000000000080 /* IOMMU read access */
+#define LDC_MTE_EXEC 0x0000000000000040 /* execute */
+#define LDC_MTE_WRITE 0x0000000000000020 /* read */
+#define LDC_MTE_READ 0x0000000000000010 /* write */
+#define LDC_MTE_SZALL 0x000000000000000f /* page size bits */
+#define LDC_MTE_SZ16GB 0x0000000000000007 /* 16GB page */
+#define LDC_MTE_SZ2GB 0x0000000000000006 /* 2GB page */
+#define LDC_MTE_SZ256MB 0x0000000000000005 /* 256MB page */
+#define LDC_MTE_SZ32MB 0x0000000000000004 /* 32MB page */
+#define LDC_MTE_SZ4MB 0x0000000000000003 /* 4MB page */
+#define LDC_MTE_SZ512K 0x0000000000000002 /* 512K page */
+#define LDC_MTE_SZ64K 0x0000000000000001 /* 64K page */
+#define LDC_MTE_SZ8K 0x0000000000000000 /* 8K page */
+
+#ifndef __ASSEMBLY__
+struct ldc_mtable_entry {
+ unsigned long mte;
+ unsigned long cookie;
+};
+#endif
+
+/* ldc_set_map_table()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_SET_MAP_TABLE
+ * ARG0: channel ID
+ * ARG1: table real address
+ * ARG2: num entries
+ * RET0: status
+ *
+ * Register the MTE table at the given table real address, with the
+ * specified num entries, for the LDC indicated by the given channel
+ * ID.
+ */
+#define HV_FAST_LDC_SET_MAP_TABLE 0xea
+
+/* ldc_get_map_table()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_GET_MAP_TABLE
+ * ARG0: channel ID
+ * RET0: status
+ * RET1: table real address
+ * RET2: num entries
+ *
+ * Return the configuration of the current mapping table registered
+ * for the given channel ID.
+ */
+#define HV_FAST_LDC_GET_MAP_TABLE 0xeb
+
+#define LDC_COPY_IN 0
+#define LDC_COPY_OUT 1
+
+/* ldc_copy()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_COPY
+ * ARG0: channel ID
+ * ARG1: LDC_COPY_* direction code
+ * ARG2: target real address
+ * ARG3: local real address
+ * ARG4: length in bytes
+ * RET0: status
+ * RET1: actual length in bytes
+ */
+#define HV_FAST_LDC_COPY 0xec
+
+#define LDC_MEM_READ 1
+#define LDC_MEM_WRITE 2
+#define LDC_MEM_EXEC 4
+
+/* ldc_mapin()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_MAPIN
+ * ARG0: channel ID
+ * ARG1: cookie
+ * RET0: status
+ * RET1: real address
+ * RET2: LDC_MEM_* permissions
+ */
+#define HV_FAST_LDC_MAPIN 0xed
+
+/* ldc_unmap()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_UNMAP
+ * ARG0: real address
+ * RET0: status
+ */
+#define HV_FAST_LDC_UNMAP 0xee
+
+/* ldc_revoke()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_LDC_REVOKE
+ * ARG0: channel ID
+ * ARG1: cookie
+ * ARG2: ldc_mtable_entry cookie
+ * RET0: status
+ */
+#define HV_FAST_LDC_REVOKE 0xef
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_ldc_tx_qconf(unsigned long channel,
+ unsigned long ra,
+ unsigned long num_entries);
+unsigned long sun4v_ldc_tx_qinfo(unsigned long channel,
+ unsigned long *ra,
+ unsigned long *num_entries);
+unsigned long sun4v_ldc_tx_get_state(unsigned long channel,
+ unsigned long *head_off,
+ unsigned long *tail_off,
+ unsigned long *chan_state);
+unsigned long sun4v_ldc_tx_set_qtail(unsigned long channel,
+ unsigned long tail_off);
+unsigned long sun4v_ldc_rx_qconf(unsigned long channel,
+ unsigned long ra,
+ unsigned long num_entries);
+unsigned long sun4v_ldc_rx_qinfo(unsigned long channel,
+ unsigned long *ra,
+ unsigned long *num_entries);
+unsigned long sun4v_ldc_rx_get_state(unsigned long channel,
+ unsigned long *head_off,
+ unsigned long *tail_off,
+ unsigned long *chan_state);
+unsigned long sun4v_ldc_rx_set_qhead(unsigned long channel,
+ unsigned long head_off);
+unsigned long sun4v_ldc_set_map_table(unsigned long channel,
+ unsigned long ra,
+ unsigned long num_entries);
+unsigned long sun4v_ldc_get_map_table(unsigned long channel,
+ unsigned long *ra,
+ unsigned long *num_entries);
+unsigned long sun4v_ldc_copy(unsigned long channel,
+ unsigned long dir_code,
+ unsigned long tgt_raddr,
+ unsigned long lcl_raddr,
+ unsigned long len,
+ unsigned long *actual_len);
+unsigned long sun4v_ldc_mapin(unsigned long channel,
+ unsigned long cookie,
+ unsigned long *ra,
+ unsigned long *perm);
+unsigned long sun4v_ldc_unmap(unsigned long ra);
+unsigned long sun4v_ldc_revoke(unsigned long channel,
+ unsigned long cookie,
+ unsigned long mte_cookie);
+#endif
+
+/* Performance counter services. */
+
+#define HV_PERF_JBUS_PERF_CTRL_REG 0x00
+#define HV_PERF_JBUS_PERF_CNT_REG 0x01
+#define HV_PERF_DRAM_PERF_CTRL_REG_0 0x02
+#define HV_PERF_DRAM_PERF_CNT_REG_0 0x03
+#define HV_PERF_DRAM_PERF_CTRL_REG_1 0x04
+#define HV_PERF_DRAM_PERF_CNT_REG_1 0x05
+#define HV_PERF_DRAM_PERF_CTRL_REG_2 0x06
+#define HV_PERF_DRAM_PERF_CNT_REG_2 0x07
+#define HV_PERF_DRAM_PERF_CTRL_REG_3 0x08
+#define HV_PERF_DRAM_PERF_CNT_REG_3 0x09
+
+/* get_perfreg()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_GET_PERFREG
+ * ARG0: performance reg number
+ * RET0: status
+ * RET1: performance reg value
+ * ERRORS: EINVAL Invalid performance register number
+ * ENOACCESS No access allowed to performance counters
+ *
+ * Read the value of the given DRAM/JBUS performance counter/control register.
+ */
+#define HV_FAST_GET_PERFREG 0x100
+
+/* set_perfreg()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_SET_PERFREG
+ * ARG0: performance reg number
+ * ARG1: performance reg value
+ * RET0: status
+ * ERRORS: EINVAL Invalid performance register number
+ * ENOACCESS No access allowed to performance counters
+ *
+ * Write the given performance reg value to the given DRAM/JBUS
+ * performance counter/control register.
+ */
+#define HV_FAST_SET_PERFREG 0x101
+
+#define HV_N2_PERF_SPARC_CTL 0x0
+#define HV_N2_PERF_DRAM_CTL0 0x1
+#define HV_N2_PERF_DRAM_CNT0 0x2
+#define HV_N2_PERF_DRAM_CTL1 0x3
+#define HV_N2_PERF_DRAM_CNT1 0x4
+#define HV_N2_PERF_DRAM_CTL2 0x5
+#define HV_N2_PERF_DRAM_CNT2 0x6
+#define HV_N2_PERF_DRAM_CTL3 0x7
+#define HV_N2_PERF_DRAM_CNT3 0x8
+
+#define HV_FAST_N2_GET_PERFREG 0x104
+#define HV_FAST_N2_SET_PERFREG 0x105
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_niagara_getperf(unsigned long reg,
+ unsigned long *val);
+unsigned long sun4v_niagara_setperf(unsigned long reg,
+ unsigned long val);
+unsigned long sun4v_niagara2_getperf(unsigned long reg,
+ unsigned long *val);
+unsigned long sun4v_niagara2_setperf(unsigned long reg,
+ unsigned long val);
+#endif
+
+/* MMU statistics services.
+ *
+ * The hypervisor maintains MMU statistics and privileged code provides
+ * a buffer where these statistics can be collected. It is continually
+ * updated once configured. The layout is as follows:
+ */
+#ifndef __ASSEMBLY__
+struct hv_mmu_statistics {
+ unsigned long immu_tsb_hits_ctx0_8k_tte;
+ unsigned long immu_tsb_ticks_ctx0_8k_tte;
+ unsigned long immu_tsb_hits_ctx0_64k_tte;
+ unsigned long immu_tsb_ticks_ctx0_64k_tte;
+ unsigned long __reserved1[2];
+ unsigned long immu_tsb_hits_ctx0_4mb_tte;
+ unsigned long immu_tsb_ticks_ctx0_4mb_tte;
+ unsigned long __reserved2[2];
+ unsigned long immu_tsb_hits_ctx0_256mb_tte;
+ unsigned long immu_tsb_ticks_ctx0_256mb_tte;
+ unsigned long __reserved3[4];
+ unsigned long immu_tsb_hits_ctxnon0_8k_tte;
+ unsigned long immu_tsb_ticks_ctxnon0_8k_tte;
+ unsigned long immu_tsb_hits_ctxnon0_64k_tte;
+ unsigned long immu_tsb_ticks_ctxnon0_64k_tte;
+ unsigned long __reserved4[2];
+ unsigned long immu_tsb_hits_ctxnon0_4mb_tte;
+ unsigned long immu_tsb_ticks_ctxnon0_4mb_tte;
+ unsigned long __reserved5[2];
+ unsigned long immu_tsb_hits_ctxnon0_256mb_tte;
+ unsigned long immu_tsb_ticks_ctxnon0_256mb_tte;
+ unsigned long __reserved6[4];
+ unsigned long dmmu_tsb_hits_ctx0_8k_tte;
+ unsigned long dmmu_tsb_ticks_ctx0_8k_tte;
+ unsigned long dmmu_tsb_hits_ctx0_64k_tte;
+ unsigned long dmmu_tsb_ticks_ctx0_64k_tte;
+ unsigned long __reserved7[2];
+ unsigned long dmmu_tsb_hits_ctx0_4mb_tte;
+ unsigned long dmmu_tsb_ticks_ctx0_4mb_tte;
+ unsigned long __reserved8[2];
+ unsigned long dmmu_tsb_hits_ctx0_256mb_tte;
+ unsigned long dmmu_tsb_ticks_ctx0_256mb_tte;
+ unsigned long __reserved9[4];
+ unsigned long dmmu_tsb_hits_ctxnon0_8k_tte;
+ unsigned long dmmu_tsb_ticks_ctxnon0_8k_tte;
+ unsigned long dmmu_tsb_hits_ctxnon0_64k_tte;
+ unsigned long dmmu_tsb_ticks_ctxnon0_64k_tte;
+ unsigned long __reserved10[2];
+ unsigned long dmmu_tsb_hits_ctxnon0_4mb_tte;
+ unsigned long dmmu_tsb_ticks_ctxnon0_4mb_tte;
+ unsigned long __reserved11[2];
+ unsigned long dmmu_tsb_hits_ctxnon0_256mb_tte;
+ unsigned long dmmu_tsb_ticks_ctxnon0_256mb_tte;
+ unsigned long __reserved12[4];
+};
+#endif
+
+/* mmustat_conf()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMUSTAT_CONF
+ * ARG0: real address
+ * RET0: status
+ * RET1: real address
+ * ERRORS: ENORADDR Invalid real address
+ * EBADALIGN Real address not aligned on 64-byte boundary
+ * EBADTRAP API not supported on this processor
+ *
+ * Enable MMU statistic gathering using the buffer at the given real
+ * address on the current virtual CPU. The new buffer real address
+ * is given in ARG1, and the previously specified buffer real address
+ * is returned in RET1, or is returned as zero for the first invocation.
+ *
+ * If the passed in real address argument is zero, this will disable
+ * MMU statistic collection on the current virtual CPU. If an error is
+ * returned then no statistics are collected.
+ *
+ * The buffer contents should be initialized to all zeros before being
+ * given to the hypervisor or else the statistics will be meaningless.
+ */
+#define HV_FAST_MMUSTAT_CONF 0x102
+
+/* mmustat_info()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_MMUSTAT_INFO
+ * RET0: status
+ * RET1: real address
+ * ERRORS: EBADTRAP API not supported on this processor
+ *
+ * Return the current state and real address of the currently configured
+ * MMU statistics buffer on the current virtual CPU.
+ */
+#define HV_FAST_MMUSTAT_INFO 0x103
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_mmustat_conf(unsigned long ra, unsigned long *orig_ra);
+unsigned long sun4v_mmustat_info(unsigned long *ra);
+#endif
+
+/* NCS crypto services */
+
+/* ncs_request() sub-function numbers */
+#define HV_NCS_QCONF 0x01
+#define HV_NCS_QTAIL_UPDATE 0x02
+
+#ifndef __ASSEMBLY__
+struct hv_ncs_queue_entry {
+ /* MAU Control Register */
+ unsigned long mau_control;
+#define MAU_CONTROL_INV_PARITY 0x0000000000002000
+#define MAU_CONTROL_STRAND 0x0000000000001800
+#define MAU_CONTROL_BUSY 0x0000000000000400
+#define MAU_CONTROL_INT 0x0000000000000200
+#define MAU_CONTROL_OP 0x00000000000001c0
+#define MAU_CONTROL_OP_SHIFT 6
+#define MAU_OP_LOAD_MA_MEMORY 0x0
+#define MAU_OP_STORE_MA_MEMORY 0x1
+#define MAU_OP_MODULAR_MULT 0x2
+#define MAU_OP_MODULAR_REDUCE 0x3
+#define MAU_OP_MODULAR_EXP_LOOP 0x4
+#define MAU_CONTROL_LEN 0x000000000000003f
+#define MAU_CONTROL_LEN_SHIFT 0
+
+ /* Real address of bytes to load or store bytes
+ * into/out-of the MAU.
+ */
+ unsigned long mau_mpa;
+
+ /* Modular Arithmetic MA Offset Register. */
+ unsigned long mau_ma;
+
+ /* Modular Arithmetic N Prime Register. */
+ unsigned long mau_np;
+};
+
+struct hv_ncs_qconf_arg {
+ unsigned long mid; /* MAU ID, 1 per core on Niagara */
+ unsigned long base; /* Real address base of queue */
+ unsigned long end; /* Real address end of queue */
+ unsigned long num_ents; /* Number of entries in queue */
+};
+
+struct hv_ncs_qtail_update_arg {
+ unsigned long mid; /* MAU ID, 1 per core on Niagara */
+ unsigned long tail; /* New tail index to use */
+ unsigned long syncflag; /* only SYNCFLAG_SYNC is implemented */
+#define HV_NCS_SYNCFLAG_SYNC 0x00
+#define HV_NCS_SYNCFLAG_ASYNC 0x01
+};
+#endif
+
+/* ncs_request()
+ * TRAP: HV_FAST_TRAP
+ * FUNCTION: HV_FAST_NCS_REQUEST
+ * ARG0: NCS sub-function
+ * ARG1: sub-function argument real address
+ * ARG2: size in bytes of sub-function argument
+ * RET0: status
+ *
+ * The MAU chip of the Niagara processor is not directly accessible
+ * to privileged code, instead it is programmed indirectly via this
+ * hypervisor API.
+ *
+ * The interfaces defines a queue of MAU operations to perform.
+ * Privileged code registers a queue with the hypervisor by invoking
+ * this HVAPI with the HV_NCS_QCONF sub-function, which defines the
+ * base, end, and number of entries of the queue. Each queue entry
+ * contains a MAU register struct block.
+ *
+ * The privileged code then proceeds to add entries to the queue and
+ * then invoke the HV_NCS_QTAIL_UPDATE sub-function. Since only
+ * synchronous operations are supported by the current hypervisor,
+ * HV_NCS_QTAIL_UPDATE will run all the pending queue entries to
+ * completion and return HV_EOK, or return an error code.
+ *
+ * The real address of the sub-function argument must be aligned on at
+ * least an 8-byte boundary.
+ *
+ * The tail argument of HV_NCS_QTAIL_UPDATE is an index, not a byte
+ * offset, into the queue and must be less than or equal the 'num_ents'
+ * argument given in the HV_NCS_QCONF call.
+ */
+#define HV_FAST_NCS_REQUEST 0x110
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_ncs_request(unsigned long request,
+ unsigned long arg_ra,
+ unsigned long arg_size);
+#endif
+
+#define HV_FAST_FIRE_GET_PERFREG 0x120
+#define HV_FAST_FIRE_SET_PERFREG 0x121
+
+#define HV_FAST_REBOOT_DATA_SET 0x172
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_reboot_data_set(unsigned long ra,
+ unsigned long len);
+#endif
+
+#define HV_FAST_VT_GET_PERFREG 0x184
+#define HV_FAST_VT_SET_PERFREG 0x185
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_vt_get_perfreg(unsigned long reg_num,
+ unsigned long *reg_val);
+unsigned long sun4v_vt_set_perfreg(unsigned long reg_num,
+ unsigned long reg_val);
+#endif
+
+#define HV_FAST_T5_GET_PERFREG 0x1a8
+#define HV_FAST_T5_SET_PERFREG 0x1a9
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_t5_get_perfreg(unsigned long reg_num,
+ unsigned long *reg_val);
+unsigned long sun4v_t5_set_perfreg(unsigned long reg_num,
+ unsigned long reg_val);
+#endif
+
+
+#define HV_FAST_M7_GET_PERFREG 0x43
+#define HV_FAST_M7_SET_PERFREG 0x44
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_m7_get_perfreg(unsigned long reg_num,
+ unsigned long *reg_val);
+unsigned long sun4v_m7_set_perfreg(unsigned long reg_num,
+ unsigned long reg_val);
+#endif
+
+/* Function numbers for HV_CORE_TRAP. */
+#define HV_CORE_SET_VER 0x00
+#define HV_CORE_PUTCHAR 0x01
+#define HV_CORE_EXIT 0x02
+#define HV_CORE_GET_VER 0x03
+
+/* Hypervisor API groups for use with HV_CORE_SET_VER and
+ * HV_CORE_GET_VER.
+ */
+#define HV_GRP_SUN4V 0x0000
+#define HV_GRP_CORE 0x0001
+#define HV_GRP_INTR 0x0002
+#define HV_GRP_SOFT_STATE 0x0003
+#define HV_GRP_TM 0x0080
+#define HV_GRP_PCI 0x0100
+#define HV_GRP_LDOM 0x0101
+#define HV_GRP_SVC_CHAN 0x0102
+#define HV_GRP_NCS 0x0103
+#define HV_GRP_RNG 0x0104
+#define HV_GRP_PBOOT 0x0105
+#define HV_GRP_TPM 0x0107
+#define HV_GRP_SDIO 0x0108
+#define HV_GRP_SDIO_ERR 0x0109
+#define HV_GRP_REBOOT_DATA 0x0110
+#define HV_GRP_ATU 0x0111
+#define HV_GRP_DAX 0x0113
+#define HV_GRP_M7_PERF 0x0114
+#define HV_GRP_NIAG_PERF 0x0200
+#define HV_GRP_FIRE_PERF 0x0201
+#define HV_GRP_N2_CPU 0x0202
+#define HV_GRP_NIU 0x0204
+#define HV_GRP_VF_CPU 0x0205
+#define HV_GRP_KT_CPU 0x0209
+#define HV_GRP_VT_CPU 0x020c
+#define HV_GRP_T5_CPU 0x0211
+#define HV_GRP_DIAG 0x0300
+
+#ifndef __ASSEMBLY__
+unsigned long sun4v_get_version(unsigned long group,
+ unsigned long *major,
+ unsigned long *minor);
+unsigned long sun4v_set_version(unsigned long group,
+ unsigned long major,
+ unsigned long minor,
+ unsigned long *actual_minor);
+
+int sun4v_hvapi_register(unsigned long group, unsigned long major,
+ unsigned long *minor);
+void sun4v_hvapi_unregister(unsigned long group);
+int sun4v_hvapi_get(unsigned long group,
+ unsigned long *major,
+ unsigned long *minor);
+void sun4v_hvapi_init(void);
+#endif
+
+#endif /* !(_SPARC64_HYPERVISOR_H) */
diff --git a/arch/sparc/include/asm/idprom.h b/arch/sparc/include/asm/idprom.h
new file mode 100644
index 000000000..4c372199c
--- /dev/null
+++ b/arch/sparc/include/asm/idprom.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * idprom.h: Macros and defines for idprom routines
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_IDPROM_H
+#define _SPARC_IDPROM_H
+
+#include <linux/types.h>
+
+struct idprom {
+ u8 id_format; /* Format identifier (always 0x01) */
+ u8 id_machtype; /* Machine type */
+ u8 id_ethaddr[6]; /* Hardware ethernet address */
+ s32 id_date; /* Date of manufacture */
+ u32 id_sernum:24; /* Unique serial number */
+ u8 id_cksum; /* Checksum - xor of the data bytes */
+ u8 reserved[16];
+};
+
+extern struct idprom *idprom;
+void idprom_init(void);
+
+#endif /* !(_SPARC_IDPROM_H) */
diff --git a/arch/sparc/include/asm/intr_queue.h b/arch/sparc/include/asm/intr_queue.h
new file mode 100644
index 000000000..d61be2a3a
--- /dev/null
+++ b/arch/sparc/include/asm/intr_queue.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_INTR_QUEUE_H
+#define _SPARC64_INTR_QUEUE_H
+
+/* Sun4v interrupt queue registers, accessed via ASI_QUEUE. */
+
+#define INTRQ_CPU_MONDO_HEAD 0x3c0 /* CPU mondo head */
+#define INTRQ_CPU_MONDO_TAIL 0x3c8 /* CPU mondo tail */
+#define INTRQ_DEVICE_MONDO_HEAD 0x3d0 /* Device mondo head */
+#define INTRQ_DEVICE_MONDO_TAIL 0x3d8 /* Device mondo tail */
+#define INTRQ_RESUM_MONDO_HEAD 0x3e0 /* Resumable error mondo head */
+#define INTRQ_RESUM_MONDO_TAIL 0x3e8 /* Resumable error mondo tail */
+#define INTRQ_NONRESUM_MONDO_HEAD 0x3f0 /* Non-resumable error mondo head */
+#define INTRQ_NONRESUM_MONDO_TAIL 0x3f8 /* Non-resumable error mondo head */
+
+#endif /* !(_SPARC64_INTR_QUEUE_H) */
diff --git a/arch/sparc/include/asm/io-unit.h b/arch/sparc/include/asm/io-unit.h
new file mode 100644
index 000000000..8c38f5b9f
--- /dev/null
+++ b/arch/sparc/include/asm/io-unit.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* io-unit.h: Definitions for the sun4d IO-UNIT.
+ *
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+#ifndef _SPARC_IO_UNIT_H
+#define _SPARC_IO_UNIT_H
+
+#include <linux/spinlock.h>
+#include <linux/pgtable.h>
+#include <asm/page.h>
+
+/* The io-unit handles all virtual to physical address translations
+ * that occur between the SBUS and physical memory. Access by
+ * the cpu to IO registers and similar go over the xdbus so are
+ * translated by the on chip SRMMU. The io-unit and the srmmu do
+ * not need to have the same translations at all, in fact most
+ * of the time the translations they handle are a disjunct set.
+ * Basically the io-unit handles all dvma sbus activity.
+ */
+
+/* AIEEE, unlike the nice sun4m, these monsters have
+ fixed DMA range 64M */
+
+#define IOUNIT_DMA_BASE 0xfc000000 /* TOP - 64M */
+#define IOUNIT_DMA_SIZE 0x04000000 /* 64M */
+/* We use last 1M for sparc_dvma_malloc */
+#define IOUNIT_DVMA_SIZE 0x00100000 /* 1M */
+
+/* The format of an iopte in the external page tables */
+#define IOUPTE_PAGE 0xffffff00 /* Physical page number (PA[35:12]) */
+#define IOUPTE_CACHE 0x00000080 /* Cached (in Viking/MXCC) */
+/* XXX Jakub, find out how to program SBUS streaming cache on XDBUS/sun4d.
+ * XXX Actually, all you should need to do is find out where the registers
+ * XXX are and copy over the sparc64 implementation I wrote. There may be
+ * XXX some horrible hwbugs though, so be careful. -DaveM
+ */
+#define IOUPTE_STREAM 0x00000040 /* Translation can use streaming cache */
+#define IOUPTE_INTRA 0x00000008 /* SBUS direct slot->slot transfer */
+#define IOUPTE_WRITE 0x00000004 /* Writeable */
+#define IOUPTE_VALID 0x00000002 /* IOPTE is valid */
+#define IOUPTE_PARITY 0x00000001 /* Parity is checked during DVMA */
+
+struct iounit_struct {
+ unsigned long bmap[(IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 3)) / sizeof(unsigned long)];
+ spinlock_t lock;
+ iopte_t __iomem *page_table;
+ unsigned long rotor[3];
+ unsigned long limit[4];
+};
+
+#define IOUNIT_BMAP1_START 0x00000000
+#define IOUNIT_BMAP1_END (IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 1))
+#define IOUNIT_BMAP2_START IOUNIT_BMAP1_END
+#define IOUNIT_BMAP2_END IOUNIT_BMAP2_START + (IOUNIT_DMA_SIZE >> (PAGE_SHIFT + 2))
+#define IOUNIT_BMAPM_START IOUNIT_BMAP2_END
+#define IOUNIT_BMAPM_END ((IOUNIT_DMA_SIZE - IOUNIT_DVMA_SIZE) >> PAGE_SHIFT)
+
+#endif /* !(_SPARC_IO_UNIT_H) */
diff --git a/arch/sparc/include/asm/io.h b/arch/sparc/include/asm/io.h
new file mode 100644
index 000000000..2dad9be9e
--- /dev/null
+++ b/arch/sparc/include/asm/io.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_IO_H
+#define ___ASM_SPARC_IO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/io_64.h>
+#else
+#include <asm/io_32.h>
+#endif
+
+/*
+ * Defines used for both SPARC32 and SPARC64
+ */
+
+/* Big endian versions of memory read/write routines */
+#define readb_be(__addr) __raw_readb(__addr)
+#define readw_be(__addr) __raw_readw(__addr)
+#define readl_be(__addr) __raw_readl(__addr)
+#define writeb_be(__b, __addr) __raw_writeb(__b, __addr)
+#define writel_be(__w, __addr) __raw_writel(__w, __addr)
+#define writew_be(__l, __addr) __raw_writew(__l, __addr)
+
+#include <asm-generic/io.h>
+
+#endif
diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h
new file mode 100644
index 000000000..549f0a722
--- /dev/null
+++ b/arch/sparc/include/asm/io_32.h
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_IO_H
+#define __SPARC_IO_H
+
+#include <linux/kernel.h>
+#include <linux/ioport.h> /* struct resource */
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define memset_io(d,c,sz) _memset_io(d,c,sz)
+#define memcpy_fromio(d,s,sz) _memcpy_fromio(d,s,sz)
+#define memcpy_toio(d,s,sz) _memcpy_toio(d,s,sz)
+
+/*
+ * Bus number may be embedded in the higher bits of the physical address.
+ * This is why we have no bus number argument to ioremap().
+ */
+void __iomem *ioremap(phys_addr_t offset, size_t size);
+void iounmap(volatile void __iomem *addr);
+
+#include <asm-generic/io.h>
+
+static inline void _memset_io(volatile void __iomem *dst,
+ int c, __kernel_size_t n)
+{
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ writeb(c, d);
+ d++;
+ }
+}
+
+static inline void _memcpy_fromio(void *dst, const volatile void __iomem *src,
+ __kernel_size_t n)
+{
+ char *d = dst;
+
+ while (n--) {
+ char tmp = readb(src);
+ *d++ = tmp;
+ src++;
+ }
+}
+
+static inline void _memcpy_toio(volatile void __iomem *dst, const void *src,
+ __kernel_size_t n)
+{
+ const char *s = src;
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ char tmp = *s++;
+ writeb(tmp, d);
+ d++;
+ }
+}
+
+/*
+ * SBus accessors.
+ *
+ * SBus has only one, memory mapped, I/O space.
+ * We do not need to flip bytes for SBus of course.
+ */
+static inline u8 sbus_readb(const volatile void __iomem *addr)
+{
+ return *(__force volatile u8 *)addr;
+}
+
+static inline u16 sbus_readw(const volatile void __iomem *addr)
+{
+ return *(__force volatile u16 *)addr;
+}
+
+static inline u32 sbus_readl(const volatile void __iomem *addr)
+{
+ return *(__force volatile u32 *)addr;
+}
+
+static inline void sbus_writeb(u8 b, volatile void __iomem *addr)
+{
+ *(__force volatile u8 *)addr = b;
+}
+
+static inline void sbus_writew(u16 w, volatile void __iomem *addr)
+{
+ *(__force volatile u16 *)addr = w;
+}
+
+static inline void sbus_writel(u32 l, volatile void __iomem *addr)
+{
+ *(__force volatile u32 *)addr = l;
+}
+
+static inline void sbus_memset_io(volatile void __iomem *__dst, int c,
+ __kernel_size_t n)
+{
+ while(n--) {
+ sbus_writeb(c, __dst);
+ __dst++;
+ }
+}
+
+static inline void sbus_memcpy_fromio(void *dst,
+ const volatile void __iomem *src,
+ __kernel_size_t n)
+{
+ char *d = dst;
+
+ while (n--) {
+ char tmp = sbus_readb(src);
+ *d++ = tmp;
+ src++;
+ }
+}
+
+static inline void sbus_memcpy_toio(volatile void __iomem *dst,
+ const void *src,
+ __kernel_size_t n)
+{
+ const char *s = src;
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ char tmp = *s++;
+ sbus_writeb(tmp, d);
+ d++;
+ }
+}
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr);
+void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+static inline int sbus_can_dma_64bit(void)
+{
+ return 0; /* actually, sparc_cpu_model==sun4d */
+}
+static inline int sbus_can_burst64(void)
+{
+ return 0; /* actually, sparc_cpu_model==sun4d */
+}
+struct device;
+void sbus_set_sbus64(struct device *, int);
+
+#define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1
+
+
+#endif /* !(__SPARC_IO_H) */
diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h
new file mode 100644
index 000000000..9303270b2
--- /dev/null
+++ b/arch/sparc/include/asm/io_64.h
@@ -0,0 +1,481 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC64_IO_H
+#define __SPARC64_IO_H
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include <asm/page.h> /* IO address mapping routines need this */
+#include <asm/asi.h>
+#include <asm-generic/pci_iomap.h>
+#define pci_iomap pci_iomap
+
+/* BIO layer definitions. */
+extern unsigned long kern_base, kern_size;
+
+/* __raw_{read,write}{b,w,l,q} uses direct access.
+ * Access the memory as big endian bypassing the cache
+ * by using ASI_PHYS_BYPASS_EC_E
+ */
+#define __raw_readb __raw_readb
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+ u8 ret;
+
+ __asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_raw_readb */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+#define __raw_readw __raw_readw
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+ u16 ret;
+
+ __asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_raw_readw */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+#define __raw_readl __raw_readl
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+ u32 ret;
+
+ __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_raw_readl */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+#define __raw_readq __raw_readq
+static inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+ u64 ret;
+
+ __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_raw_readq */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+#define __raw_writeb __raw_writeb
+static inline void __raw_writeb(u8 b, const volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_raw_writeb */"
+ : /* no outputs */
+ : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define __raw_writew __raw_writew
+static inline void __raw_writew(u16 w, const volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_raw_writew */"
+ : /* no outputs */
+ : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define __raw_writel __raw_writel
+static inline void __raw_writel(u32 l, const volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_raw_writel */"
+ : /* no outputs */
+ : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define __raw_writeq __raw_writeq
+static inline void __raw_writeq(u64 q, const volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_raw_writeq */"
+ : /* no outputs */
+ : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+/* Memory functions, same as I/O accesses on Ultra.
+ * Access memory as little endian bypassing
+ * the cache by using ASI_PHYS_BYPASS_EC_E_L
+ */
+#define readb readb
+#define readb_relaxed readb
+static inline u8 readb(const volatile void __iomem *addr)
+{ u8 ret;
+
+ __asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+ return ret;
+}
+
+#define readw readw
+#define readw_relaxed readw
+static inline u16 readw(const volatile void __iomem *addr)
+{ u16 ret;
+
+ __asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+#define readl readl
+#define readl_relaxed readl
+static inline u32 readl(const volatile void __iomem *addr)
+{ u32 ret;
+
+ __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+#define readq readq
+#define readq_relaxed readq
+static inline u64 readq(const volatile void __iomem *addr)
+{ u64 ret;
+
+ __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* pci_readq */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+
+ return ret;
+}
+
+#define writeb writeb
+#define writeb_relaxed writeb
+static inline void writeb(u8 b, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
+ : /* no outputs */
+ : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+#define writew writew
+#define writew_relaxed writew
+static inline void writew(u16 w, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
+ : /* no outputs */
+ : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+#define writel writel
+#define writel_relaxed writel
+static inline void writel(u32 l, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
+ : /* no outputs */
+ : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+#define writeq writeq
+#define writeq_relaxed writeq
+static inline void writeq(u64 q, volatile void __iomem *addr)
+{
+ __asm__ __volatile__("stxa\t%r0, [%1] %2\t/* pci_writeq */"
+ : /* no outputs */
+ : "Jr" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+ : "memory");
+}
+
+#define inb inb
+static inline u8 inb(unsigned long addr)
+{
+ return readb((volatile void __iomem *)addr);
+}
+
+#define inw inw
+static inline u16 inw(unsigned long addr)
+{
+ return readw((volatile void __iomem *)addr);
+}
+
+#define inl inl
+static inline u32 inl(unsigned long addr)
+{
+ return readl((volatile void __iomem *)addr);
+}
+
+#define outb outb
+static inline void outb(u8 b, unsigned long addr)
+{
+ writeb(b, (volatile void __iomem *)addr);
+}
+
+#define outw outw
+static inline void outw(u16 w, unsigned long addr)
+{
+ writew(w, (volatile void __iomem *)addr);
+}
+
+#define outl outl
+static inline void outl(u32 l, unsigned long addr)
+{
+ writel(l, (volatile void __iomem *)addr);
+}
+
+
+#define inb_p(__addr) inb(__addr)
+#define outb_p(__b, __addr) outb(__b, __addr)
+#define inw_p(__addr) inw(__addr)
+#define outw_p(__w, __addr) outw(__w, __addr)
+#define inl_p(__addr) inl(__addr)
+#define outl_p(__l, __addr) outl(__l, __addr)
+
+void outsb(unsigned long, const void *, unsigned long);
+void outsw(unsigned long, const void *, unsigned long);
+void outsl(unsigned long, const void *, unsigned long);
+#define outsb outsb
+#define outsw outsw
+#define outsl outsl
+void insb(unsigned long, void *, unsigned long);
+void insw(unsigned long, void *, unsigned long);
+void insl(unsigned long, void *, unsigned long);
+#define insb insb
+#define insw insw
+#define insl insl
+
+static inline void readsb(void __iomem *port, void *buf, unsigned long count)
+{
+ insb((unsigned long __force)port, buf, count);
+}
+#define readsb readsb
+
+static inline void readsw(void __iomem *port, void *buf, unsigned long count)
+{
+ insw((unsigned long __force)port, buf, count);
+}
+#define readsw readsw
+
+static inline void readsl(void __iomem *port, void *buf, unsigned long count)
+{
+ insl((unsigned long __force)port, buf, count);
+}
+#define readsl readsl
+
+static inline void writesb(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsb((unsigned long __force)port, buf, count);
+}
+#define writesb writesb
+
+static inline void writesw(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsw((unsigned long __force)port, buf, count);
+}
+#define writesw writesw
+
+static inline void writesl(void __iomem *port, const void *buf, unsigned long count)
+{
+ outsl((unsigned long __force)port, buf, count);
+}
+#define writesl writesl
+
+#define ioread8_rep(p,d,l) readsb(p,d,l)
+#define ioread16_rep(p,d,l) readsw(p,d,l)
+#define ioread32_rep(p,d,l) readsl(p,d,l)
+#define iowrite8_rep(p,d,l) writesb(p,d,l)
+#define iowrite16_rep(p,d,l) writesw(p,d,l)
+#define iowrite32_rep(p,d,l) writesl(p,d,l)
+
+/* Valid I/O Space regions are anywhere, because each PCI bus supported
+ * can live in an arbitrary area of the physical address range.
+ */
+#define IO_SPACE_LIMIT 0xffffffffffffffffUL
+
+/* Now, SBUS variants, only difference from PCI is that we do
+ * not use little-endian ASIs.
+ */
+static inline u8 sbus_readb(const volatile void __iomem *addr)
+{
+ return __raw_readb(addr);
+}
+
+static inline u16 sbus_readw(const volatile void __iomem *addr)
+{
+ return __raw_readw(addr);
+}
+
+static inline u32 sbus_readl(const volatile void __iomem *addr)
+{
+ return __raw_readl(addr);
+}
+
+static inline u64 sbus_readq(const volatile void __iomem *addr)
+{
+ return __raw_readq(addr);
+}
+
+static inline void sbus_writeb(u8 b, volatile void __iomem *addr)
+{
+ __raw_writeb(b, addr);
+}
+
+static inline void sbus_writew(u16 w, volatile void __iomem *addr)
+{
+ __raw_writew(w, addr);
+}
+
+static inline void sbus_writel(u32 l, volatile void __iomem *addr)
+{
+ __raw_writel(l, addr);
+}
+
+static inline void sbus_writeq(u64 q, volatile void __iomem *addr)
+{
+ __raw_writeq(q, addr);
+}
+
+static inline void sbus_memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+{
+ while(n--) {
+ sbus_writeb(c, dst);
+ dst++;
+ }
+}
+
+static inline void memset_io(volatile void __iomem *dst, int c, __kernel_size_t n)
+{
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ writeb(c, d);
+ d++;
+ }
+}
+#define memset_io memset_io
+
+static inline void sbus_memcpy_fromio(void *dst, const volatile void __iomem *src,
+ __kernel_size_t n)
+{
+ char *d = dst;
+
+ while (n--) {
+ char tmp = sbus_readb(src);
+ *d++ = tmp;
+ src++;
+ }
+}
+
+
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
+ __kernel_size_t n)
+{
+ char *d = dst;
+
+ while (n--) {
+ char tmp = readb(src);
+ *d++ = tmp;
+ src++;
+ }
+}
+#define memcpy_fromio memcpy_fromio
+
+static inline void sbus_memcpy_toio(volatile void __iomem *dst, const void *src,
+ __kernel_size_t n)
+{
+ const char *s = src;
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ char tmp = *s++;
+ sbus_writeb(tmp, d);
+ d++;
+ }
+}
+
+static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
+ __kernel_size_t n)
+{
+ const char *s = src;
+ volatile void __iomem *d = dst;
+
+ while (n--) {
+ char tmp = *s++;
+ writeb(tmp, d);
+ d++;
+ }
+}
+#define memcpy_toio memcpy_toio
+
+#ifdef __KERNEL__
+
+/* On sparc64 we have the whole physical IO address space accessible
+ * using physically addressed loads and stores, so this does nothing.
+ */
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
+{
+ return (void __iomem *)offset;
+}
+
+#define ioremap_uc(X,Y) ioremap((X),(Y))
+#define ioremap_wc(X,Y) ioremap((X),(Y))
+#define ioremap_wt(X,Y) ioremap((X),(Y))
+static inline void __iomem *ioremap_np(unsigned long offset, unsigned long size)
+{
+ return NULL;
+
+}
+#define ioremap_np ioremap_np
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+}
+
+#define ioread8 readb
+#define ioread16 readw
+#define ioread16be __raw_readw
+#define ioread32 readl
+#define ioread32be __raw_readl
+#define iowrite8 writeb
+#define iowrite16 writew
+#define iowrite16be __raw_writew
+#define iowrite32 writel
+#define iowrite32be __raw_writel
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr);
+void ioport_unmap(void __iomem *);
+#define ioport_map ioport_map
+#define ioport_unmap ioport_unmap
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+void pci_iounmap(struct pci_dev *dev, void __iomem *);
+#define pci_iounmap pci_iounmap
+
+static inline int sbus_can_dma_64bit(void)
+{
+ return 1;
+}
+static inline int sbus_can_burst64(void)
+{
+ return 1;
+}
+struct device;
+void sbus_set_sbus64(struct device *, int);
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+#endif
+
+#endif /* !(__SPARC64_IO_H) */
diff --git a/arch/sparc/include/asm/ioctls.h b/arch/sparc/include/asm/ioctls.h
new file mode 100644
index 000000000..c92ac780c
--- /dev/null
+++ b/arch/sparc/include/asm/ioctls.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC_IOCTLS_H
+#define _ASM_SPARC_IOCTLS_H
+
+#include <uapi/asm/ioctls.h>
+
+#define TIOCGETC __TIOCGETC
+#define TIOCGETP __TIOCGETP
+#define TIOCGLTC __TIOCGLTC
+#define TIOCSLTC __TIOCSLTC
+#define TIOCSETP __TIOCSETP
+#define TIOCSETN __TIOCSETN
+#define TIOCSETC __TIOCSETC
+#endif /* !(_ASM_SPARC_IOCTLS_H) */
diff --git a/arch/sparc/include/asm/iommu-common.h b/arch/sparc/include/asm/iommu-common.h
new file mode 100644
index 000000000..802c90c79
--- /dev/null
+++ b/arch/sparc/include/asm/iommu-common.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_IOMMU_COMMON_H
+#define _LINUX_IOMMU_COMMON_H
+
+#include <linux/spinlock_types.h>
+#include <linux/device.h>
+#include <asm/page.h>
+
+#define IOMMU_POOL_HASHBITS 4
+#define IOMMU_NR_POOLS (1 << IOMMU_POOL_HASHBITS)
+#define IOMMU_ERROR_CODE (~(unsigned long) 0)
+
+struct iommu_pool {
+ unsigned long start;
+ unsigned long end;
+ unsigned long hint;
+ spinlock_t lock;
+};
+
+struct iommu_map_table {
+ unsigned long table_map_base;
+ unsigned long table_shift;
+ unsigned long nr_pools;
+ void (*lazy_flush)(struct iommu_map_table *);
+ unsigned long poolsize;
+ struct iommu_pool pools[IOMMU_NR_POOLS];
+ u32 flags;
+#define IOMMU_HAS_LARGE_POOL 0x00000001
+#define IOMMU_NO_SPAN_BOUND 0x00000002
+#define IOMMU_NEED_FLUSH 0x00000004
+ struct iommu_pool large_pool;
+ unsigned long *map;
+};
+
+extern void iommu_tbl_pool_init(struct iommu_map_table *iommu,
+ unsigned long num_entries,
+ u32 table_shift,
+ void (*lazy_flush)(struct iommu_map_table *),
+ bool large_pool, u32 npools,
+ bool skip_span_boundary_check);
+
+extern unsigned long iommu_tbl_range_alloc(struct device *dev,
+ struct iommu_map_table *iommu,
+ unsigned long npages,
+ unsigned long *handle,
+ unsigned long mask,
+ unsigned int align_order);
+
+extern void iommu_tbl_range_free(struct iommu_map_table *iommu,
+ u64 dma_addr, unsigned long npages,
+ unsigned long entry);
+
+#endif
diff --git a/arch/sparc/include/asm/iommu.h b/arch/sparc/include/asm/iommu.h
new file mode 100644
index 000000000..37935cb34
--- /dev/null
+++ b/arch/sparc/include/asm/iommu.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_IOMMU_H
+#define ___ASM_SPARC_IOMMU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/iommu_64.h>
+#else
+#include <asm/iommu_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/iommu_32.h b/arch/sparc/include/asm/iommu_32.h
new file mode 100644
index 000000000..af51cd5ea
--- /dev/null
+++ b/arch/sparc/include/asm/iommu_32.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* iommu.h: Definitions for the sun4m IOMMU.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_IOMMU_H
+#define _SPARC_IOMMU_H
+
+#include <asm/page.h>
+#include <asm/bitext.h>
+
+/* The iommu handles all virtual to physical address translations
+ * that occur between the SBUS and physical memory. Access by
+ * the cpu to IO registers and similar go over the mbus so are
+ * translated by the on chip SRMMU. The iommu and the srmmu do
+ * not need to have the same translations at all, in fact most
+ * of the time the translations they handle are a disjunct set.
+ * Basically the iommu handles all dvma sbus activity.
+ */
+
+/* The IOMMU registers occupy three pages in IO space. */
+struct iommu_regs {
+ /* First page */
+ volatile unsigned long control; /* IOMMU control */
+ volatile unsigned long base; /* Physical base of iopte page table */
+ volatile unsigned long _unused1[3];
+ volatile unsigned long tlbflush; /* write only */
+ volatile unsigned long pageflush; /* write only */
+ volatile unsigned long _unused2[1017];
+ /* Second page */
+ volatile unsigned long afsr; /* Async-fault status register */
+ volatile unsigned long afar; /* Async-fault physical address */
+ volatile unsigned long _unused3[2];
+ volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */
+ volatile unsigned long sbuscfg1;
+ volatile unsigned long sbuscfg2;
+ volatile unsigned long sbuscfg3;
+ volatile unsigned long mfsr; /* Memory-fault status register */
+ volatile unsigned long mfar; /* Memory-fault physical address */
+ volatile unsigned long _unused4[1014];
+ /* Third page */
+ volatile unsigned long mid; /* IOMMU module-id */
+};
+
+#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
+#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
+#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
+#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
+#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
+#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
+#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
+#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
+#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
+#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
+#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
+#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
+
+#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
+#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */
+#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */
+#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */
+#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
+#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */
+#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
+#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */
+#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
+
+#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
+#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
+#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
+#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
+ produced by this device as pure
+ physical. */
+
+#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */
+#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */
+#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */
+#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred
+ on the even word of the access, low bit
+ indicated odd word caused the parity error */
+#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */
+#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */
+#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */
+
+#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */
+#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */
+#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */
+#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */
+#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */
+#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */
+#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */
+
+/* The format of an iopte in the page tables */
+#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
+#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
+#define IOPTE_WRITE 0x00000004 /* Writeable */
+#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
+#define IOPTE_WAZ 0x00000001 /* Write as zeros */
+
+struct iommu_struct {
+ struct iommu_regs __iomem *regs;
+ iopte_t *page_table;
+ /* For convenience */
+ unsigned long start; /* First managed virtual address */
+ unsigned long end; /* Last managed virtual address */
+
+ struct bit_map usemap;
+};
+
+static inline void iommu_invalidate(struct iommu_regs __iomem *regs)
+{
+ sbus_writel(0, &regs->tlbflush);
+}
+
+static inline void iommu_invalidate_page(struct iommu_regs __iomem *regs, unsigned long ba)
+{
+ sbus_writel(ba & PAGE_MASK, &regs->pageflush);
+}
+
+#endif /* !(_SPARC_IOMMU_H) */
diff --git a/arch/sparc/include/asm/iommu_64.h b/arch/sparc/include/asm/iommu_64.h
new file mode 100644
index 000000000..0ef6dedf7
--- /dev/null
+++ b/arch/sparc/include/asm/iommu_64.h
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* iommu.h: Definitions for the sun5 IOMMU.
+ *
+ * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
+ */
+#ifndef _SPARC64_IOMMU_H
+#define _SPARC64_IOMMU_H
+
+/* The format of an iopte in the page tables. */
+#define IOPTE_VALID 0x8000000000000000UL
+#define IOPTE_64K 0x2000000000000000UL
+#define IOPTE_STBUF 0x1000000000000000UL
+#define IOPTE_INTRA 0x0800000000000000UL
+#define IOPTE_CONTEXT 0x07ff800000000000UL
+#define IOPTE_PAGE 0x00007fffffffe000UL
+#define IOPTE_CACHE 0x0000000000000010UL
+#define IOPTE_WRITE 0x0000000000000002UL
+
+#define IOMMU_NUM_CTXS 4096
+#include <asm/iommu-common.h>
+
+struct iommu_arena {
+ unsigned long *map;
+ unsigned int hint;
+ unsigned int limit;
+};
+
+#define ATU_64_SPACE_SIZE 0x800000000 /* 32G */
+
+/* Data structures for SPARC ATU architecture */
+struct atu_iotsb {
+ void *table; /* IOTSB table base virtual addr*/
+ u64 ra; /* IOTSB table real addr */
+ u64 dvma_size; /* ranges[3].size or OS slected 32G size */
+ u64 dvma_base; /* ranges[3].base */
+ u64 table_size; /* IOTSB table size */
+ u64 page_size; /* IO PAGE size for IOTSB */
+ u32 iotsb_num; /* tsbnum is same as iotsb_handle */
+};
+
+struct atu_ranges {
+ u64 base;
+ u64 size;
+};
+
+struct atu {
+ struct atu_ranges *ranges;
+ struct atu_iotsb *iotsb;
+ struct iommu_map_table tbl;
+ u64 base;
+ u64 size;
+ u64 dma_addr_mask;
+};
+
+struct iommu {
+ struct iommu_map_table tbl;
+ struct atu *atu;
+ spinlock_t lock;
+ u32 dma_addr_mask;
+ iopte_t *page_table;
+ unsigned long iommu_control;
+ unsigned long iommu_tsbbase;
+ unsigned long iommu_flush;
+ unsigned long iommu_flushinv;
+ unsigned long iommu_tags;
+ unsigned long iommu_ctxflush;
+ unsigned long write_complete_reg;
+ unsigned long dummy_page;
+ unsigned long dummy_page_pa;
+ unsigned long ctx_lowest_free;
+ DECLARE_BITMAP(ctx_bitmap, IOMMU_NUM_CTXS);
+};
+
+struct strbuf {
+ int strbuf_enabled;
+ unsigned long strbuf_control;
+ unsigned long strbuf_pflush;
+ unsigned long strbuf_fsync;
+ unsigned long strbuf_err_stat;
+ unsigned long strbuf_tag_diag;
+ unsigned long strbuf_line_diag;
+ unsigned long strbuf_ctxflush;
+ unsigned long strbuf_ctxmatch_base;
+ unsigned long strbuf_flushflag_pa;
+ volatile unsigned long *strbuf_flushflag;
+ volatile unsigned long __flushflag_buf[(64+(64-1)) / sizeof(long)];
+};
+
+int iommu_table_init(struct iommu *iommu, int tsbsize,
+ u32 dma_offset, u32 dma_addr_mask,
+ int numa_node);
+
+#endif /* !(_SPARC64_IOMMU_H) */
diff --git a/arch/sparc/include/asm/irq.h b/arch/sparc/include/asm/irq.h
new file mode 100644
index 000000000..a2efc274d
--- /dev/null
+++ b/arch/sparc/include/asm/irq.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_IRQ_H
+#define ___ASM_SPARC_IRQ_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/irq_64.h>
+#else
+#include <asm/irq_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h
new file mode 100644
index 000000000..6ee48321c
--- /dev/null
+++ b/arch/sparc/include/asm/irq_32.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* irq.h: IRQ registers on the Sparc.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC_IRQ_H
+#define _SPARC_IRQ_H
+
+/* Allocated number of logical irq numbers.
+ * sun4d boxes (ss2000e) should be OK with ~32.
+ * Be on the safe side and make room for 64
+ */
+#define NR_IRQS 64
+
+#include <linux/interrupt.h>
+
+#define irq_canonicalize(irq) (irq)
+
+void __init sun4d_init_sbi_irq(void);
+
+#define NO_IRQ 0xffffffff
+
+#endif
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h
new file mode 100644
index 000000000..8c4c0c87f
--- /dev/null
+++ b/arch/sparc/include/asm/irq_64.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* irq.h: IRQ registers on the 64-bit Sparc.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#ifndef _SPARC64_IRQ_H
+#define _SPARC64_IRQ_H
+
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <asm/pil.h>
+#include <asm/ptrace.h>
+
+/* IMAP/ICLR register defines */
+#define IMAP_VALID 0x80000000UL /* IRQ Enabled */
+#define IMAP_TID_UPA 0x7c000000UL /* UPA TargetID */
+#define IMAP_TID_JBUS 0x7c000000UL /* JBUS TargetID */
+#define IMAP_TID_SHIFT 26
+#define IMAP_AID_SAFARI 0x7c000000UL /* Safari AgentID */
+#define IMAP_AID_SHIFT 26
+#define IMAP_NID_SAFARI 0x03e00000UL /* Safari NodeID */
+#define IMAP_NID_SHIFT 21
+#define IMAP_IGN 0x000007c0UL /* IRQ Group Number */
+#define IMAP_INO 0x0000003fUL /* IRQ Number */
+#define IMAP_INR 0x000007ffUL /* Full interrupt number*/
+
+#define ICLR_IDLE 0x00000000UL /* Idle state */
+#define ICLR_TRANSMIT 0x00000001UL /* Transmit state */
+#define ICLR_PENDING 0x00000003UL /* Pending state */
+
+/* The largest number of unique interrupt sources we support.
+ * If this needs to ever be larger than 255, you need to change
+ * the type of ino_bucket->irq as appropriate.
+ *
+ * ino_bucket->irq allocation is made during {sun4v_,}build_irq().
+ */
+#define NR_IRQS (2048)
+
+void irq_install_pre_handler(int irq,
+ void (*func)(unsigned int, void *, void *),
+ void *arg1, void *arg2);
+#define irq_canonicalize(irq) (irq)
+unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
+unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
+unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino);
+unsigned int sun4v_build_msi(u32 devhandle, unsigned int *irq_p,
+ unsigned int msi_devino_start,
+ unsigned int msi_devino_end);
+void sun4v_destroy_msi(unsigned int irq);
+unsigned int sun4u_build_msi(u32 portid, unsigned int *irq_p,
+ unsigned int msi_devino_start,
+ unsigned int msi_devino_end,
+ unsigned long imap_base,
+ unsigned long iclr_base);
+void sun4u_destroy_msi(unsigned int irq);
+
+unsigned int irq_alloc(unsigned int dev_handle, unsigned int dev_ino);
+void irq_free(unsigned int irq);
+
+void fixup_irqs(void);
+
+static inline void set_softint(unsigned long bits)
+{
+ __asm__ __volatile__("wr %0, 0x0, %%set_softint"
+ : /* No outputs */
+ : "r" (bits));
+}
+
+static inline void clear_softint(unsigned long bits)
+{
+ __asm__ __volatile__("wr %0, 0x0, %%clear_softint"
+ : /* No outputs */
+ : "r" (bits));
+}
+
+static inline unsigned long get_softint(void)
+{
+ unsigned long retval;
+
+ __asm__ __volatile__("rd %%softint, %0"
+ : "=r" (retval));
+ return retval;
+}
+
+void arch_trigger_cpumask_backtrace(const struct cpumask *mask,
+ int exclude_cpu);
+#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
+
+extern void *hardirq_stack[NR_CPUS];
+extern void *softirq_stack[NR_CPUS];
+
+#define NO_IRQ 0xffffffff
+
+#endif
diff --git a/arch/sparc/include/asm/irqflags.h b/arch/sparc/include/asm/irqflags.h
new file mode 100644
index 000000000..d1bdf6c39
--- /dev/null
+++ b/arch/sparc/include/asm/irqflags.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_IRQFLAGS_H
+#define ___ASM_SPARC_IRQFLAGS_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/irqflags_64.h>
+#else
+#include <asm/irqflags_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/irqflags_32.h b/arch/sparc/include/asm/irqflags_32.h
new file mode 100644
index 000000000..7ca3eaf3d
--- /dev/null
+++ b/arch/sparc/include/asm/irqflags_32.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * include/asm/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * arch_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <asm/psr.h>
+
+void arch_local_irq_restore(unsigned long);
+unsigned long arch_local_irq_save(void);
+void arch_local_irq_enable(void);
+
+static inline notrace unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+
+ asm volatile("rd %%psr, %0" : "=r" (flags));
+ return flags;
+}
+
+static inline notrace void arch_local_irq_disable(void)
+{
+ arch_local_irq_save();
+}
+
+static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags & PSR_PIL) != 0;
+}
+
+static inline notrace bool arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/arch/sparc/include/asm/irqflags_64.h b/arch/sparc/include/asm/irqflags_64.h
new file mode 100644
index 000000000..c29ed571a
--- /dev/null
+++ b/arch/sparc/include/asm/irqflags_64.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * include/asm/irqflags.h
+ *
+ * IRQ flags handling
+ *
+ * This file gets included from lowlevel asm headers too, to provide
+ * wrapped versions of the local_irq_*() APIs, based on the
+ * arch_local_irq_*() functions from the lowlevel headers.
+ */
+#ifndef _ASM_IRQFLAGS_H
+#define _ASM_IRQFLAGS_H
+
+#include <asm/pil.h>
+
+#ifndef __ASSEMBLY__
+
+static inline notrace unsigned long arch_local_save_flags(void)
+{
+ unsigned long flags;
+
+ __asm__ __volatile__(
+ "rdpr %%pil, %0"
+ : "=r" (flags)
+ );
+
+ return flags;
+}
+
+static inline notrace void arch_local_irq_restore(unsigned long flags)
+{
+ __asm__ __volatile__(
+ "wrpr %0, %%pil"
+ : /* no output */
+ : "r" (flags)
+ : "memory"
+ );
+}
+
+static inline notrace void arch_local_irq_disable(void)
+{
+ __asm__ __volatile__(
+ "wrpr %0, %%pil"
+ : /* no outputs */
+ : "i" (PIL_NORMAL_MAX)
+ : "memory"
+ );
+}
+
+static inline notrace void arch_local_irq_enable(void)
+{
+ __asm__ __volatile__(
+ "wrpr 0, %%pil"
+ : /* no outputs */
+ : /* no inputs */
+ : "memory"
+ );
+}
+
+static inline notrace int arch_irqs_disabled_flags(unsigned long flags)
+{
+ return (flags > 0);
+}
+
+static inline notrace int arch_irqs_disabled(void)
+{
+ return arch_irqs_disabled_flags(arch_local_save_flags());
+}
+
+static inline notrace unsigned long arch_local_irq_save(void)
+{
+ unsigned long flags, tmp;
+
+ /* Disable interrupts to PIL_NORMAL_MAX unless we already
+ * are using PIL_NMI, in which case PIL_NMI is retained.
+ *
+ * The only values we ever program into the %pil are 0,
+ * PIL_NORMAL_MAX and PIL_NMI.
+ *
+ * Since PIL_NMI is the largest %pil value and all bits are
+ * set in it (0xf), it doesn't matter what PIL_NORMAL_MAX
+ * actually is.
+ */
+ __asm__ __volatile__(
+ "rdpr %%pil, %0\n\t"
+ "or %0, %2, %1\n\t"
+ "wrpr %1, 0x0, %%pil"
+ : "=r" (flags), "=r" (tmp)
+ : "i" (PIL_NORMAL_MAX)
+ : "memory"
+ );
+
+ return flags;
+}
+
+#endif /* (__ASSEMBLY__) */
+
+#endif /* !(_ASM_IRQFLAGS_H) */
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
new file mode 100644
index 000000000..94eb529dc
--- /dev/null
+++ b/arch/sparc/include/asm/jump_label.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC_JUMP_LABEL_H
+#define _ASM_SPARC_JUMP_LABEL_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
+{
+ asm_volatile_goto("1:\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ ".pushsection __jump_table, \"aw\"\n\t"
+ ".align 4\n\t"
+ ".word 1b, %l[l_yes], %c0\n\t"
+ ".popsection \n\t"
+ : : "i" (&((char *)key)[branch]) : : l_yes);
+
+ return false;
+l_yes:
+ return true;
+}
+
+static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
+{
+ asm_volatile_goto("1:\n\t"
+ "b %l[l_yes]\n\t"
+ "nop\n\t"
+ ".pushsection __jump_table, \"aw\"\n\t"
+ ".align 4\n\t"
+ ".word 1b, %l[l_yes], %c0\n\t"
+ ".popsection \n\t"
+ : : "i" (&((char *)key)[branch]) : : l_yes);
+
+ return false;
+l_yes:
+ return true;
+}
+
+typedef u32 jump_label_t;
+
+struct jump_entry {
+ jump_label_t code;
+ jump_label_t target;
+ jump_label_t key;
+};
+
+#endif /* __ASSEMBLY__ */
+#endif
diff --git a/arch/sparc/include/asm/kdebug.h b/arch/sparc/include/asm/kdebug.h
new file mode 100644
index 000000000..830053f91
--- /dev/null
+++ b/arch/sparc/include/asm/kdebug.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_KDEBUG_H
+#define ___ASM_SPARC_KDEBUG_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/kdebug_64.h>
+#else
+#include <asm/kdebug_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/kdebug_32.h b/arch/sparc/include/asm/kdebug_32.h
new file mode 100644
index 000000000..763d42382
--- /dev/null
+++ b/arch/sparc/include/asm/kdebug_32.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * kdebug.h: Defines and definitions for debugging the Linux kernel
+ * under various kernel debuggers.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_KDEBUG_H
+#define _SPARC_KDEBUG_H
+
+#include <asm/openprom.h>
+#include <asm/vaddrs.h>
+
+/* Breakpoints are enter through trap table entry 126. So in sparc assembly
+ * if you want to drop into the debugger you do:
+ *
+ * t DEBUG_BP_TRAP
+ */
+
+#define DEBUG_BP_TRAP 126
+
+#ifndef __ASSEMBLY__
+/* The debug vector is passed in %o1 at boot time. It is a pointer to
+ * a structure in the debuggers address space. Here is its format.
+ */
+
+typedef unsigned int (*debugger_funct)(void);
+
+struct kernel_debug {
+ /* First the entry point into the debugger. You jump here
+ * to give control over to the debugger.
+ */
+ unsigned long kdebug_entry;
+ unsigned long kdebug_trapme; /* Figure out later... */
+ /* The following is the number of pages that the debugger has
+ * taken from to total pool.
+ */
+ unsigned long *kdebug_stolen_pages;
+ /* Ok, after you remap yourself and/or change the trap table
+ * from what you were left with at boot time you have to call
+ * this synchronization function so the debugger can check out
+ * what you have done.
+ */
+ debugger_funct teach_debugger;
+}; /* I think that is it... */
+
+extern struct kernel_debug *linux_dbvec;
+
+/* Use this macro in C-code to enter the debugger. */
+static inline void sp_enter_debugger(void)
+{
+ __asm__ __volatile__("jmpl %0, %%o7\n\t"
+ "nop\n\t" : :
+ "r" (linux_dbvec) : "o7", "memory");
+}
+
+#define SP_ENTER_DEBUGGER do { \
+ if((linux_dbvec!=0) && ((*(short *)linux_dbvec)!=-1)) \
+ sp_enter_debugger(); \
+ } while(0)
+
+enum die_val {
+ DIE_UNUSED,
+ DIE_OOPS,
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+/* Some nice offset defines for assembler code. */
+#define KDEBUG_ENTRY_OFF 0x0
+#define KDEBUG_DUNNO_OFF 0x4
+#define KDEBUG_DUNNO2_OFF 0x8
+#define KDEBUG_TEACH_OFF 0xc
+
+#endif /* !(_SPARC_KDEBUG_H) */
diff --git a/arch/sparc/include/asm/kdebug_64.h b/arch/sparc/include/asm/kdebug_64.h
new file mode 100644
index 000000000..89428bd4f
--- /dev/null
+++ b/arch/sparc/include/asm/kdebug_64.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_KDEBUG_H
+#define _SPARC64_KDEBUG_H
+
+struct pt_regs;
+
+void bad_trap(struct pt_regs *, long);
+
+/* Grossly misnamed. */
+enum die_val {
+ DIE_OOPS = 1,
+ DIE_DEBUG, /* ta 0x70 */
+ DIE_DEBUG_2, /* ta 0x71 */
+ DIE_BPT, /* ta 0x73 */
+ DIE_SSTEP, /* ta 0x74 */
+ DIE_DIE,
+ DIE_TRAP,
+ DIE_TRAP_TL1,
+ DIE_CALL,
+ DIE_NMI,
+ DIE_NMIWATCHDOG,
+};
+
+#endif
diff --git a/arch/sparc/include/asm/kgdb.h b/arch/sparc/include/asm/kgdb.h
new file mode 100644
index 000000000..deabe0279
--- /dev/null
+++ b/arch/sparc/include/asm/kgdb.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_KGDB_H
+#define _SPARC_KGDB_H
+
+#ifdef CONFIG_SPARC32
+#define BUFMAX 2048
+#else
+#define BUFMAX 4096
+#endif
+
+enum regnames {
+ GDB_G0, GDB_G1, GDB_G2, GDB_G3, GDB_G4, GDB_G5, GDB_G6, GDB_G7,
+ GDB_O0, GDB_O1, GDB_O2, GDB_O3, GDB_O4, GDB_O5, GDB_SP, GDB_O7,
+ GDB_L0, GDB_L1, GDB_L2, GDB_L3, GDB_L4, GDB_L5, GDB_L6, GDB_L7,
+ GDB_I0, GDB_I1, GDB_I2, GDB_I3, GDB_I4, GDB_I5, GDB_FP, GDB_I7,
+ GDB_F0,
+ GDB_F31 = GDB_F0 + 31,
+#ifdef CONFIG_SPARC32
+ GDB_Y, GDB_PSR, GDB_WIM, GDB_TBR, GDB_PC, GDB_NPC,
+ GDB_FSR, GDB_CSR,
+#else
+ GDB_F32 = GDB_F0 + 32,
+ GDB_F62 = GDB_F32 + 15,
+ GDB_PC, GDB_NPC, GDB_STATE, GDB_FSR, GDB_FPRS, GDB_Y,
+#endif
+};
+
+#ifdef CONFIG_SPARC32
+#define NUMREGBYTES ((GDB_CSR + 1) * 4)
+#else
+#define NUMREGBYTES ((GDB_Y + 1) * 8)
+#endif
+
+struct pt_regs;
+asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs);
+
+void arch_kgdb_breakpoint(void);
+
+#define BREAK_INSTR_SIZE 4
+#define CACHE_FLUSH_IS_SAFE 1
+
+#endif /* _SPARC_KGDB_H */
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
new file mode 100644
index 000000000..06c2bc767
--- /dev/null
+++ b/arch/sparc/include/asm/kprobes.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_KPROBES_H
+#define _SPARC64_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION 0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
+#include <linux/types.h>
+#include <linux/percpu.h>
+
+typedef u32 kprobe_opcode_t;
+
+#define MAX_INSN_SIZE 2
+
+#define kretprobe_blacklist_size 0
+
+#define arch_remove_kprobe(p) do {} while (0)
+
+#define flush_insn_slot(p) \
+do { flushi(&(p)->ainsn.insn[0]); \
+ flushi(&(p)->ainsn.insn[1]); \
+} while (0)
+
+void __kretprobe_trampoline(void);
+
+/* Architecture specific copy of original instruction*/
+struct arch_specific_insn {
+ /* copy of the original instruction */
+ kprobe_opcode_t insn[MAX_INSN_SIZE];
+};
+
+struct prev_kprobe {
+ struct kprobe *kp;
+ unsigned long status;
+ unsigned long orig_tnpc;
+ unsigned long orig_tstate_pil;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+ unsigned long kprobe_status;
+ unsigned long kprobe_orig_tnpc;
+ unsigned long kprobe_orig_tstate_pil;
+ struct prev_kprobe prev_kprobe;
+};
+
+int kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data);
+int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
+ struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
+#endif /* _SPARC64_KPROBES_H */
diff --git a/arch/sparc/include/asm/ldc.h b/arch/sparc/include/asm/ldc.h
new file mode 100644
index 000000000..ca973955c
--- /dev/null
+++ b/arch/sparc/include/asm/ldc.h
@@ -0,0 +1,149 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_LDC_H
+#define _SPARC64_LDC_H
+
+#include <asm/hypervisor.h>
+
+extern int ldom_domaining_enabled;
+void ldom_set_var(const char *var, const char *value);
+void ldom_reboot(const char *boot_command);
+void ldom_power_off(void);
+
+/* The event handler will be evoked when link state changes
+ * or data becomes available on the receive side.
+ *
+ * For non-RAW links, if the LDC_EVENT_RESET event arrives the
+ * driver should reset all of it's internal state and reinvoke
+ * ldc_connect() to try and bring the link up again.
+ *
+ * For RAW links, ldc_connect() is not used. Instead the driver
+ * just waits for the LDC_EVENT_UP event.
+ */
+struct ldc_channel_config {
+ void (*event)(void *arg, int event);
+
+ u32 mtu;
+ unsigned int rx_irq;
+ unsigned int tx_irq;
+ u8 mode;
+#define LDC_MODE_RAW 0x00
+#define LDC_MODE_UNRELIABLE 0x01
+#define LDC_MODE_RESERVED 0x02
+#define LDC_MODE_STREAM 0x03
+
+ u8 debug;
+#define LDC_DEBUG_HS 0x01
+#define LDC_DEBUG_STATE 0x02
+#define LDC_DEBUG_RX 0x04
+#define LDC_DEBUG_TX 0x08
+#define LDC_DEBUG_DATA 0x10
+};
+
+#define LDC_EVENT_RESET 0x01
+#define LDC_EVENT_UP 0x02
+#define LDC_EVENT_DATA_READY 0x04
+
+#define LDC_STATE_INVALID 0x00
+#define LDC_STATE_INIT 0x01
+#define LDC_STATE_BOUND 0x02
+#define LDC_STATE_READY 0x03
+#define LDC_STATE_CONNECTED 0x04
+
+#define LDC_PACKET_SIZE 64
+
+struct ldc_channel;
+
+/* Allocate state for a channel. */
+struct ldc_channel *ldc_alloc(unsigned long id,
+ const struct ldc_channel_config *cfgp,
+ void *event_arg,
+ const char *name);
+
+/* Shut down and free state for a channel. */
+void ldc_free(struct ldc_channel *lp);
+
+/* Register TX and RX queues of the link with the hypervisor. */
+int ldc_bind(struct ldc_channel *lp);
+void ldc_unbind(struct ldc_channel *lp);
+
+/* For non-RAW protocols we need to complete a handshake before
+ * communication can proceed. ldc_connect() does that, if the
+ * handshake completes successfully, an LDC_EVENT_UP event will
+ * be sent up to the driver.
+ */
+int ldc_connect(struct ldc_channel *lp);
+int ldc_disconnect(struct ldc_channel *lp);
+
+int ldc_state(struct ldc_channel *lp);
+void ldc_set_state(struct ldc_channel *lp, u8 state);
+int ldc_mode(struct ldc_channel *lp);
+void __ldc_print(struct ldc_channel *lp, const char *caller);
+int ldc_rx_reset(struct ldc_channel *lp);
+
+#define ldc_print(chan) __ldc_print(chan, __func__)
+
+/* Read and write operations. Only valid when the link is up. */
+int ldc_write(struct ldc_channel *lp, const void *buf,
+ unsigned int size);
+int ldc_read(struct ldc_channel *lp, void *buf, unsigned int size);
+
+#define LDC_MAP_SHADOW 0x01
+#define LDC_MAP_DIRECT 0x02
+#define LDC_MAP_IO 0x04
+#define LDC_MAP_R 0x08
+#define LDC_MAP_W 0x10
+#define LDC_MAP_X 0x20
+#define LDC_MAP_RW (LDC_MAP_R | LDC_MAP_W)
+#define LDC_MAP_RWX (LDC_MAP_R | LDC_MAP_W | LDC_MAP_X)
+#define LDC_MAP_ALL 0x03f
+
+struct ldc_trans_cookie {
+ u64 cookie_addr;
+ u64 cookie_size;
+};
+
+struct scatterlist;
+int ldc_map_sg(struct ldc_channel *lp,
+ struct scatterlist *sg, int num_sg,
+ struct ldc_trans_cookie *cookies, int ncookies,
+ unsigned int map_perm);
+
+int ldc_map_single(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies,
+ unsigned int map_perm);
+
+void ldc_unmap(struct ldc_channel *lp, struct ldc_trans_cookie *cookies,
+ int ncookies);
+
+int ldc_copy(struct ldc_channel *lp, int copy_dir,
+ void *buf, unsigned int len, unsigned long offset,
+ struct ldc_trans_cookie *cookies, int ncookies);
+
+static inline int ldc_get_dring_entry(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ unsigned long offset,
+ struct ldc_trans_cookie *cookies,
+ int ncookies)
+{
+ return ldc_copy(lp, LDC_COPY_IN, buf, len, offset, cookies, ncookies);
+}
+
+static inline int ldc_put_dring_entry(struct ldc_channel *lp,
+ void *buf, unsigned int len,
+ unsigned long offset,
+ struct ldc_trans_cookie *cookies,
+ int ncookies)
+{
+ return ldc_copy(lp, LDC_COPY_OUT, buf, len, offset, cookies, ncookies);
+}
+
+void *ldc_alloc_exp_dring(struct ldc_channel *lp, unsigned int len,
+ struct ldc_trans_cookie *cookies,
+ int *ncookies, unsigned int map_perm);
+
+void ldc_free_exp_dring(struct ldc_channel *lp, void *buf,
+ unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies);
+
+#endif /* _SPARC64_LDC_H */
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
new file mode 100644
index 000000000..c1e05e4ab
--- /dev/null
+++ b/arch/sparc/include/asm/leon.h
@@ -0,0 +1,266 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2004 Konrad Eisele (eiselekd@web.de,konrad@gaisler.com) Gaisler Research
+ * Copyright (C) 2004 Stefan Holst (mail@s-holst.de) Uni-Stuttgart
+ * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
+ * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
+ */
+
+#ifndef LEON_H_INCLUDE
+#define LEON_H_INCLUDE
+
+/* mmu register access, ASI_LEON_MMUREGS */
+#define LEON_CNR_CTRL 0x000
+#define LEON_CNR_CTXP 0x100
+#define LEON_CNR_CTX 0x200
+#define LEON_CNR_F 0x300
+#define LEON_CNR_FADDR 0x400
+
+#define LEON_CNR_CTX_NCTX 256 /*number of MMU ctx */
+
+#define LEON_CNR_CTRL_TLBDIS 0x80000000
+
+#define LEON_MMUTLB_ENT_MAX 64
+
+/*
+ * diagnostic access from mmutlb.vhd:
+ * 0: pte address
+ * 4: pte
+ * 8: additional flags
+ */
+#define LEON_DIAGF_LVL 0x3
+#define LEON_DIAGF_WR 0x8
+#define LEON_DIAGF_WR_SHIFT 3
+#define LEON_DIAGF_HIT 0x10
+#define LEON_DIAGF_HIT_SHIFT 4
+#define LEON_DIAGF_CTX 0x1fe0
+#define LEON_DIAGF_CTX_SHIFT 5
+#define LEON_DIAGF_VALID 0x2000
+#define LEON_DIAGF_VALID_SHIFT 13
+
+/* irq masks */
+#define LEON_HARD_INT(x) (1 << (x)) /* irq 0-15 */
+#define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 of lregs.irqmask */
+#define LEON_IRQPRIO_R 0xfffe0000 /* bit 31-17 of lregs.irqmask */
+
+#define LEON_MCFG2_SRAMDIS 0x00002000
+#define LEON_MCFG2_SDRAMEN 0x00004000
+#define LEON_MCFG2_SRAMBANKSZ 0x00001e00 /* [12-9] */
+#define LEON_MCFG2_SRAMBANKSZ_SHIFT 9
+#define LEON_MCFG2_SDRAMBANKSZ 0x03800000 /* [25-23] */
+#define LEON_MCFG2_SDRAMBANKSZ_SHIFT 23
+
+#define LEON_TCNT0_MASK 0x7fffff
+
+
+#define ASI_LEON3_SYSCTRL 0x02
+#define ASI_LEON3_SYSCTRL_ICFG 0x08
+#define ASI_LEON3_SYSCTRL_DCFG 0x0c
+#define ASI_LEON3_SYSCTRL_CFG_SNOOPING (1 << 27)
+#define ASI_LEON3_SYSCTRL_CFG_SSIZE(c) (1 << ((c >> 20) & 0xf))
+
+#ifndef __ASSEMBLY__
+
+/* do a physical address bypass write, i.e. for 0x80000000 */
+static inline void leon_store_reg(unsigned long paddr, unsigned long value)
+{
+ __asm__ __volatile__("sta %0, [%1] %2\n\t" : : "r"(value), "r"(paddr),
+ "i"(ASI_LEON_BYPASS) : "memory");
+}
+
+/* do a physical address bypass load, i.e. for 0x80000000 */
+static inline unsigned long leon_load_reg(unsigned long paddr)
+{
+ unsigned long retval;
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r"(retval) : "r"(paddr), "i"(ASI_LEON_BYPASS));
+ return retval;
+}
+
+/* macro access for leon_load_reg() and leon_store_reg() */
+#define LEON3_BYPASS_LOAD_PA(x) (leon_load_reg((unsigned long)(x)))
+#define LEON3_BYPASS_STORE_PA(x, v) (leon_store_reg((unsigned long)(x), (unsigned long)(v)))
+#define LEON_BYPASS_LOAD_PA(x) leon_load_reg((unsigned long)(x))
+#define LEON_BYPASS_STORE_PA(x, v) leon_store_reg((unsigned long)(x), (unsigned long)(v))
+
+void leon_switch_mm(void);
+void leon_init_IRQ(void);
+
+static inline unsigned long sparc_leon3_get_dcachecfg(void)
+{
+ unsigned int retval;
+ __asm__ __volatile__("lda [%1] %2, %0\n\t" :
+ "=r"(retval) :
+ "r"(ASI_LEON3_SYSCTRL_DCFG),
+ "i"(ASI_LEON3_SYSCTRL));
+ return retval;
+}
+
+/* enable snooping */
+static inline void sparc_leon3_enable_snooping(void)
+{
+ __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
+ "set 0x800000, %%l2\n\t"
+ "or %%l2, %%l1, %%l2\n\t"
+ "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
+};
+
+static inline int sparc_leon3_snooping_enabled(void)
+{
+ u32 cctrl;
+ __asm__ __volatile__("lda [%%g0] 2, %0\n\t" : "=r"(cctrl));
+ return ((cctrl >> 23) & 1) && ((cctrl >> 17) & 1);
+};
+
+static inline void sparc_leon3_disable_cache(void)
+{
+ __asm__ __volatile__ ("lda [%%g0] 2, %%l1\n\t"
+ "set 0x00000f, %%l2\n\t"
+ "andn %%l2, %%l1, %%l2\n\t"
+ "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2");
+};
+
+static inline unsigned long sparc_leon3_asr17(void)
+{
+ u32 asr17;
+ __asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17));
+ return asr17;
+};
+
+static inline int sparc_leon3_cpuid(void)
+{
+ return sparc_leon3_asr17() >> 28;
+}
+
+#endif /*!__ASSEMBLY__*/
+
+#ifdef CONFIG_SMP
+# define LEON3_IRQ_IPI_DEFAULT 13
+# define LEON3_IRQ_TICKER (leon3_gptimer_irq)
+# define LEON3_IRQ_CROSS_CALL 15
+#endif
+
+#if defined(PAGE_SIZE_LEON_8K)
+#define LEON_PAGE_SIZE_LEON 1
+#elif defined(PAGE_SIZE_LEON_16K)
+#define LEON_PAGE_SIZE_LEON 2)
+#else
+#define LEON_PAGE_SIZE_LEON 0
+#endif
+
+#if LEON_PAGE_SIZE_LEON == 0
+/* [ 8, 6, 6 ] + 12 */
+#define LEON_PGD_SH 24
+#define LEON_PGD_M 0xff
+#define LEON_PMD_SH 18
+#define LEON_PMD_SH_V (LEON_PGD_SH-2)
+#define LEON_PMD_M 0x3f
+#define LEON_PTE_SH 12
+#define LEON_PTE_M 0x3f
+#elif LEON_PAGE_SIZE_LEON == 1
+/* [ 7, 6, 6 ] + 13 */
+#define LEON_PGD_SH 25
+#define LEON_PGD_M 0x7f
+#define LEON_PMD_SH 19
+#define LEON_PMD_SH_V (LEON_PGD_SH-1)
+#define LEON_PMD_M 0x3f
+#define LEON_PTE_SH 13
+#define LEON_PTE_M 0x3f
+#elif LEON_PAGE_SIZE_LEON == 2
+/* [ 6, 6, 6 ] + 14 */
+#define LEON_PGD_SH 26
+#define LEON_PGD_M 0x3f
+#define LEON_PMD_SH 20
+#define LEON_PMD_SH_V (LEON_PGD_SH-0)
+#define LEON_PMD_M 0x3f
+#define LEON_PTE_SH 14
+#define LEON_PTE_M 0x3f
+#elif LEON_PAGE_SIZE_LEON == 3
+/* [ 4, 7, 6 ] + 15 */
+#define LEON_PGD_SH 28
+#define LEON_PGD_M 0x0f
+#define LEON_PMD_SH 21
+#define LEON_PMD_SH_V (LEON_PGD_SH-0)
+#define LEON_PMD_M 0x7f
+#define LEON_PTE_SH 15
+#define LEON_PTE_M 0x3f
+#else
+#error cannot determine LEON_PAGE_SIZE_LEON
+#endif
+
+#define LEON3_XCCR_SETS_MASK 0x07000000UL
+#define LEON3_XCCR_SSIZE_MASK 0x00f00000UL
+
+#define LEON2_CCR_DSETS_MASK 0x03000000UL
+#define LEON2_CFG_SSIZE_MASK 0x00007000UL
+
+#ifndef __ASSEMBLY__
+struct vm_area_struct;
+
+unsigned long leon_swprobe(unsigned long vaddr, unsigned long *paddr);
+void leon_flush_icache_all(void);
+void leon_flush_dcache_all(void);
+void leon_flush_cache_all(void);
+void leon_flush_tlb_all(void);
+extern int leon_flush_during_switch;
+int leon_flush_needed(void);
+void leon_flush_pcache_all(struct vm_area_struct *vma, unsigned long page);
+
+/* struct that hold LEON3 cache configuration registers */
+struct leon3_cacheregs {
+ unsigned long ccr; /* 0x00 - Cache Control Register */
+ unsigned long iccr; /* 0x08 - Instruction Cache Configuration Register */
+ unsigned long dccr; /* 0x0c - Data Cache Configuration Register */
+};
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+struct device_node;
+struct task_struct;
+unsigned int leon_build_device_irq(unsigned int real_irq,
+ irq_flow_handler_t flow_handler,
+ const char *name, int do_ack);
+void leon_update_virq_handling(unsigned int virq,
+ irq_flow_handler_t flow_handler,
+ const char *name, int do_ack);
+void leon_init_timers(void);
+void leon_node_init(struct device_node *dp, struct device_node ***nextp);
+void init_leon(void);
+void poke_leonsparc(void);
+void leon3_getCacheRegs(struct leon3_cacheregs *regs);
+extern int leon3_ticker_irq;
+
+#ifdef CONFIG_SMP
+int leon_smp_nrcpus(void);
+void leon_clear_profile_irq(int cpu);
+void leon_smp_done(void);
+void leon_boot_cpus(void);
+int leon_boot_one_cpu(int i, struct task_struct *);
+void leon_init_smp(void);
+void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
+irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
+
+extern unsigned int smpleon_ipi[];
+extern unsigned int linux_trap_ipi15_leon[];
+extern int leon_ipi_irq;
+
+#endif /* CONFIG_SMP */
+
+#endif /* __ASSEMBLY__ */
+
+/* macros used in leon_mm.c */
+#define PFN(x) ((x) >> PAGE_SHIFT)
+#define _pfn_valid(pfn) ((pfn < last_valid_pfn) && (pfn >= PFN(phys_base)))
+#define _SRMMU_PTE_PMASK_LEON 0xffffffff
+
+/*
+ * On LEON PCI Memory space is mapped 1:1 with physical address space.
+ *
+ * I/O space is located at low 64Kbytes in PCI I/O space. The I/O addresses
+ * are converted into CPU addresses to virtual addresses that are mapped with
+ * MMU to the PCI Host PCI I/O space window which are translated to the low
+ * 64Kbytes by the Host controller.
+ */
+
+#endif
diff --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h
new file mode 100644
index 000000000..6433a93f5
--- /dev/null
+++ b/arch/sparc/include/asm/leon_amba.h
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+*Copyright (C) 2004 Konrad Eisele (eiselekd@web.de,konrad@gaisler.com), Gaisler Research
+*Copyright (C) 2004 Stefan Holst (mail@s-holst.de), Uni-Stuttgart
+*Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com),Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
+*/
+
+#ifndef LEON_AMBA_H_INCLUDE
+#define LEON_AMBA_H_INCLUDE
+
+#ifndef __ASSEMBLY__
+
+struct amba_prom_registers {
+ unsigned int phys_addr; /* The physical address of this register */
+ unsigned int reg_size; /* How many bytes does this register take up? */
+};
+
+#endif
+
+/*
+ * The following defines the bits in the LEON UART Status Registers.
+ */
+
+#define LEON_REG_UART_STATUS_DR 0x00000001 /* Data Ready */
+#define LEON_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */
+#define LEON_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */
+#define LEON_REG_UART_STATUS_BR 0x00000008 /* Break Error */
+#define LEON_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */
+#define LEON_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */
+#define LEON_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */
+#define LEON_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */
+
+/*
+ * The following defines the bits in the LEON UART Ctrl Registers.
+ */
+
+#define LEON_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */
+#define LEON_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */
+#define LEON_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */
+#define LEON_REG_UART_CTRL_TI 0x00000008 /* Transmitter irq */
+#define LEON_REG_UART_CTRL_PS 0x00000010 /* Parity select */
+#define LEON_REG_UART_CTRL_PE 0x00000020 /* Parity enable */
+#define LEON_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */
+#define LEON_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */
+
+#define LEON3_GPTIMER_EN 1
+#define LEON3_GPTIMER_RL 2
+#define LEON3_GPTIMER_LD 4
+#define LEON3_GPTIMER_IRQEN 8
+#define LEON3_GPTIMER_SEPIRQ 8
+#define LEON3_GPTIMER_TIMERS 0x7
+
+#define LEON23_REG_TIMER_CONTROL_EN 0x00000001 /* 1 = enable counting */
+/* 0 = hold scalar and counter */
+#define LEON23_REG_TIMER_CONTROL_RL 0x00000002 /* 1 = reload at 0 */
+ /* 0 = stop at 0 */
+#define LEON23_REG_TIMER_CONTROL_LD 0x00000004 /* 1 = load counter */
+ /* 0 = no function */
+#define LEON23_REG_TIMER_CONTROL_IQ 0x00000008 /* 1 = irq enable */
+ /* 0 = no function */
+
+/*
+ * The following defines the bits in the LEON PS/2 Status Registers.
+ */
+
+#define LEON_REG_PS2_STATUS_DR 0x00000001 /* Data Ready */
+#define LEON_REG_PS2_STATUS_PE 0x00000002 /* Parity error */
+#define LEON_REG_PS2_STATUS_FE 0x00000004 /* Framing error */
+#define LEON_REG_PS2_STATUS_KI 0x00000008 /* Keyboard inhibit */
+#define LEON_REG_PS2_STATUS_RF 0x00000010 /* RX buffer full */
+#define LEON_REG_PS2_STATUS_TF 0x00000020 /* TX buffer full */
+
+/*
+ * The following defines the bits in the LEON PS/2 Ctrl Registers.
+ */
+
+#define LEON_REG_PS2_CTRL_RE 0x00000001 /* Receiver enable */
+#define LEON_REG_PS2_CTRL_TE 0x00000002 /* Transmitter enable */
+#define LEON_REG_PS2_CTRL_RI 0x00000004 /* Keyboard receive irq */
+#define LEON_REG_PS2_CTRL_TI 0x00000008 /* Keyboard transmit irq */
+
+#define LEON3_IRQMPSTATUS_CPUNR 28
+#define LEON3_IRQMPSTATUS_BROADCAST 27
+
+#define GPTIMER_CONFIG_IRQNT(a) (((a) >> 3) & 0x1f)
+#define GPTIMER_CONFIG_ISSEP(a) ((a) & (1 << 8))
+#define GPTIMER_CONFIG_NTIMERS(a) ((a) & (0x7))
+#define LEON3_GPTIMER_CTRL_PENDING 0x10
+#define LEON3_GPTIMER_CONFIG_NRTIMERS(c) ((c)->config & 0x7)
+#define LEON3_GPTIMER_CTRL_ISPENDING(r) (((r)&LEON3_GPTIMER_CTRL_PENDING) ? 1 : 0)
+
+#ifndef __ASSEMBLY__
+
+struct leon3_irqctrl_regs_map {
+ u32 ilevel;
+ u32 ipend;
+ u32 iforce;
+ u32 iclear;
+ u32 mpstatus;
+ u32 mpbroadcast;
+ u32 notused02;
+ u32 notused03;
+ u32 ampctrl;
+ u32 icsel[2];
+ u32 notused13;
+ u32 notused20;
+ u32 notused21;
+ u32 notused22;
+ u32 notused23;
+ u32 mask[16];
+ u32 force[16];
+ /* Extended IRQ registers */
+ u32 intid[16]; /* 0xc0 */
+ u32 unused[(0x1000-0x100)/4];
+};
+
+struct leon3_apbuart_regs_map {
+ u32 data;
+ u32 status;
+ u32 ctrl;
+ u32 scaler;
+};
+
+struct leon3_gptimerelem_regs_map {
+ u32 val;
+ u32 rld;
+ u32 ctrl;
+ u32 unused;
+};
+
+struct leon3_gptimer_regs_map {
+ u32 scalar;
+ u32 scalar_reload;
+ u32 config;
+ u32 unused;
+ struct leon3_gptimerelem_regs_map e[8];
+};
+
+/*
+ * Types and structure used for AMBA Plug & Play bus scanning
+ */
+
+#define AMBA_MAXAPB_DEVS 64
+#define AMBA_MAXAPB_DEVS_PERBUS 16
+
+struct amba_device_table {
+ int devnr; /* number of devices on AHB or APB bus */
+ unsigned int *addr[16]; /* addresses to the devices configuration tables */
+ unsigned int allocbits[1]; /* 0=unallocated, 1=allocated driver */
+};
+
+struct amba_apbslv_device_table {
+ int devnr; /* number of devices on AHB or APB bus */
+ unsigned int *addr[AMBA_MAXAPB_DEVS]; /* addresses to the devices configuration tables */
+ unsigned int apbmst[AMBA_MAXAPB_DEVS]; /* apb master if a entry is a apb slave */
+ unsigned int apbmstidx[AMBA_MAXAPB_DEVS]; /* apb master idx if a entry is a apb slave */
+ unsigned int allocbits[4]; /* 0=unallocated, 1=allocated driver */
+};
+
+struct amba_confarea_type {
+ struct amba_confarea_type *next;/* next bus in chain */
+ struct amba_device_table ahbmst;
+ struct amba_device_table ahbslv;
+ struct amba_apbslv_device_table apbslv;
+ unsigned int apbmst;
+};
+
+/* collect apb slaves */
+struct amba_apb_device {
+ unsigned int start, irq, bus_id;
+ struct amba_confarea_type *bus;
+};
+
+/* collect ahb slaves */
+struct amba_ahb_device {
+ unsigned int start[4], irq, bus_id;
+ struct amba_confarea_type *bus;
+};
+
+struct device_node;
+void _amba_init(struct device_node *dp, struct device_node ***nextp);
+
+extern unsigned long amba_system_id;
+extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs;
+extern struct leon3_gptimer_regs_map *leon3_gptimer_regs;
+extern struct amba_apb_device leon_percpu_timer_dev[16];
+extern int leondebug_irq_disable;
+extern int leon_debug_irqout;
+extern unsigned long leon3_gptimer_irq;
+extern unsigned int sparc_leon_eirq;
+
+#endif /* __ASSEMBLY__ */
+
+#define LEON3_IO_AREA 0xfff00000
+#define LEON3_CONF_AREA 0xff000
+#define LEON3_AHB_SLAVE_CONF_AREA (1 << 11)
+
+#define LEON3_AHB_CONF_WORDS 8
+#define LEON3_APB_CONF_WORDS 2
+#define LEON3_AHB_MASTERS 16
+#define LEON3_AHB_SLAVES 16
+#define LEON3_APB_SLAVES 16
+#define LEON3_APBUARTS 8
+
+/* Vendor codes */
+#define VENDOR_GAISLER 1
+#define VENDOR_PENDER 2
+#define VENDOR_ESA 4
+#define VENDOR_OPENCORES 8
+
+/* Gaisler Research device id's */
+#define GAISLER_LEON3 0x003
+#define GAISLER_LEON3DSU 0x004
+#define GAISLER_ETHAHB 0x005
+#define GAISLER_APBMST 0x006
+#define GAISLER_AHBUART 0x007
+#define GAISLER_SRCTRL 0x008
+#define GAISLER_SDCTRL 0x009
+#define GAISLER_APBUART 0x00C
+#define GAISLER_IRQMP 0x00D
+#define GAISLER_AHBRAM 0x00E
+#define GAISLER_GPTIMER 0x011
+#define GAISLER_PCITRG 0x012
+#define GAISLER_PCISBRG 0x013
+#define GAISLER_PCIFBRG 0x014
+#define GAISLER_PCITRACE 0x015
+#define GAISLER_PCIDMA 0x016
+#define GAISLER_AHBTRACE 0x017
+#define GAISLER_ETHDSU 0x018
+#define GAISLER_PIOPORT 0x01A
+#define GAISLER_GRGPIO 0x01A
+#define GAISLER_AHBJTAG 0x01c
+#define GAISLER_ETHMAC 0x01D
+#define GAISLER_AHB2AHB 0x020
+#define GAISLER_USBDC 0x021
+#define GAISLER_ATACTRL 0x024
+#define GAISLER_DDRSPA 0x025
+#define GAISLER_USBEHC 0x026
+#define GAISLER_USBUHC 0x027
+#define GAISLER_I2CMST 0x028
+#define GAISLER_SPICTRL 0x02D
+#define GAISLER_DDR2SPA 0x02E
+#define GAISLER_SPIMCTRL 0x045
+#define GAISLER_LEON4 0x048
+#define GAISLER_LEON4DSU 0x049
+#define GAISLER_AHBSTAT 0x052
+#define GAISLER_FTMCTRL 0x054
+#define GAISLER_KBD 0x060
+#define GAISLER_VGA 0x061
+#define GAISLER_SVGA 0x063
+#define GAISLER_GRSYSMON 0x066
+#define GAISLER_GRACECTRL 0x067
+
+#define GAISLER_L2TIME 0xffd /* internal device: leon2 timer */
+#define GAISLER_L2C 0xffe /* internal device: leon2compat */
+#define GAISLER_PLUGPLAY 0xfff /* internal device: plug & play configarea */
+
+/* Chip IDs */
+#define AEROFLEX_UT699 0x0699
+#define LEON4_NEXTREME1 0x0102
+#define GAISLER_GR712RC 0x0712
+
+#define amba_vendor(x) (((x) >> 24) & 0xff)
+
+#define amba_device(x) (((x) >> 12) & 0xfff)
+
+#endif
diff --git a/arch/sparc/include/asm/leon_pci.h b/arch/sparc/include/asm/leon_pci.h
new file mode 100644
index 000000000..484a56e81
--- /dev/null
+++ b/arch/sparc/include/asm/leon_pci.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * asm/leon_pci.h
+ *
+ * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
+ */
+
+#ifndef _ASM_LEON_PCI_H_
+#define _ASM_LEON_PCI_H_
+
+/* PCI related definitions */
+struct leon_pci_info {
+ struct pci_ops *ops;
+ struct resource io_space;
+ struct resource mem_space;
+ struct resource busn;
+ int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+};
+
+void leon_pci_init(struct platform_device *ofdev,
+ struct leon_pci_info *info);
+
+#endif /* _ASM_LEON_PCI_H_ */
diff --git a/arch/sparc/include/asm/lsu.h b/arch/sparc/include/asm/lsu.h
new file mode 100644
index 000000000..154ae76c0
--- /dev/null
+++ b/arch/sparc/include/asm/lsu.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_LSU_H
+#define _SPARC64_LSU_H
+
+#include <linux/const.h>
+
+/* LSU Control Register */
+#define LSU_CONTROL_PM _AC(0x000001fe00000000,UL) /* Phys-watchpoint byte mask*/
+#define LSU_CONTROL_VM _AC(0x00000001fe000000,UL) /* Virt-watchpoint byte mask*/
+#define LSU_CONTROL_PR _AC(0x0000000001000000,UL) /* Phys-rd watchpoint enable*/
+#define LSU_CONTROL_PW _AC(0x0000000000800000,UL) /* Phys-wr watchpoint enable*/
+#define LSU_CONTROL_VR _AC(0x0000000000400000,UL) /* Virt-rd watchpoint enable*/
+#define LSU_CONTROL_VW _AC(0x0000000000200000,UL) /* Virt-wr watchpoint enable*/
+#define LSU_CONTROL_FM _AC(0x00000000000ffff0,UL) /* Parity mask enables. */
+#define LSU_CONTROL_DM _AC(0x0000000000000008,UL) /* Data MMU enable. */
+#define LSU_CONTROL_IM _AC(0x0000000000000004,UL) /* Instruction MMU enable. */
+#define LSU_CONTROL_DC _AC(0x0000000000000002,UL) /* Data cache enable. */
+#define LSU_CONTROL_IC _AC(0x0000000000000001,UL) /* Instruction cache enable.*/
+
+#endif /* !(_SPARC64_LSU_H) */
diff --git a/arch/sparc/include/asm/machines.h b/arch/sparc/include/asm/machines.h
new file mode 100644
index 000000000..9f78f70c6
--- /dev/null
+++ b/arch/sparc/include/asm/machines.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * machines.h: Defines for taking apart the machine type value in the
+ * idprom and determining the kind of machine we are on.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_MACHINES_H
+#define _SPARC_MACHINES_H
+
+struct Sun_Machine_Models {
+ char *name;
+ unsigned char id_machtype;
+};
+
+/* The machine type in the idprom area looks like this:
+ *
+ * ---------------
+ * | ARCH | MACH |
+ * ---------------
+ * 7 4 3 0
+ *
+ * The ARCH field determines the architecture line (sun4m, etc).
+ * The MACH field determines the machine make within that architecture.
+ */
+
+#define SM_ARCH_MASK 0xf0
+#define M_LEON 0x30
+#define SM_SUN4M 0x70
+#define SM_SUN4M_OBP 0x80
+
+#define SM_TYP_MASK 0x0f
+
+/* Leon machines */
+#define M_LEON3_SOC 0x02 /* Leon3 SoC */
+
+/* Sun4m machines, these predate the OpenBoot. These values only mean
+ * something if the value in the ARCH field is SM_SUN4M, if it is
+ * SM_SUN4M_OBP then you have the following situation:
+ * 1) You either have a sun4d, a sun4e, or a recently made sun4m.
+ * 2) You have to consult OpenBoot to determine which machine this is.
+ */
+#define SM_4M_SS60 0x01 /* Sun4m SparcSystem 600 */
+#define SM_4M_SS50 0x02 /* Sun4m SparcStation 10 */
+#define SM_4M_SS40 0x03 /* Sun4m SparcStation 5 */
+
+/* Sun4d machines -- N/A */
+/* Sun4e machines -- N/A */
+/* Sun4u machines -- N/A */
+
+#endif /* !(_SPARC_MACHINES_H) */
diff --git a/arch/sparc/include/asm/mbus.h b/arch/sparc/include/asm/mbus.h
new file mode 100644
index 000000000..8b6dbe701
--- /dev/null
+++ b/arch/sparc/include/asm/mbus.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mbus.h: Various defines for MBUS modules.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_MBUS_H
+#define _SPARC_MBUS_H
+
+#include <asm/ross.h> /* HyperSparc stuff */
+#include <asm/viking.h> /* Ugh, bug city... */
+
+enum mbus_module {
+ HyperSparc = 0,
+ Swift_ok = 4,
+ Swift_bad_c = 5,
+ Swift_lots_o_bugs = 6,
+ Tsunami = 7,
+ Viking_12 = 8,
+ Viking_2x = 9,
+ Viking_30 = 10,
+ Viking_35 = 11,
+ Viking_new = 12,
+ TurboSparc = 13,
+ SRMMU_INVAL_MOD = 14,
+};
+
+extern enum mbus_module srmmu_modtype;
+extern unsigned int viking_rev, swift_rev, cypress_rev;
+
+/* HW Mbus module bugs we have to deal with */
+#define HWBUG_COPYBACK_BROKEN 0x00000001
+#define HWBUG_ASIFLUSH_BROKEN 0x00000002
+#define HWBUG_VACFLUSH_BITROT 0x00000004
+#define HWBUG_KERN_ACCBROKEN 0x00000008
+#define HWBUG_KERN_CBITBROKEN 0x00000010
+#define HWBUG_MODIFIED_BITROT 0x00000020
+#define HWBUG_PC_BADFAULT_ADDR 0x00000040
+#define HWBUG_SUPERSCALAR_BAD 0x00000080
+#define HWBUG_PACINIT_BITROT 0x00000100
+
+/* First the module type values. To find out which you have, just load
+ * the mmu control register from ASI_M_MMUREG alternate address space and
+ * shift the value right 28 bits.
+ */
+/* IMPL field means the company which produced the chip. */
+#define MBUS_VIKING 0x4 /* bleech, Texas Instruments Module */
+#define MBUS_LSI 0x3 /* LSI Logics */
+#define MBUS_ROSS 0x1 /* Ross is nice */
+#define MBUS_FMI 0x0 /* Fujitsu Microelectronics/Swift */
+
+/* Ross Module versions */
+#define ROSS_604_REV_CDE 0x0 /* revisions c, d, and e */
+#define ROSS_604_REV_F 0x1 /* revision f */
+#define ROSS_605 0xf /* revision a, a.1, and a.2 */
+#define ROSS_605_REV_B 0xe /* revision b */
+
+/* TI Viking Module versions */
+#define VIKING_REV_12 0x1 /* Version 1.2 or SPARCclassic's CPU */
+#define VIKING_REV_2 0x2 /* Version 2.1, 2.2, 2.3, and 2.4 */
+#define VIKING_REV_30 0x3 /* Version 3.0 */
+#define VIKING_REV_35 0x4 /* Version 3.5 */
+
+/* LSI Logics. */
+#define LSI_L64815 0x0
+
+/* Fujitsu */
+#define FMI_AURORA 0x4 /* MB8690x, a Swift module... */
+#define FMI_TURBO 0x5 /* MB86907, a TurboSparc module... */
+
+/* For multiprocessor support we need to be able to obtain the CPU id and
+ * the MBUS Module id.
+ */
+
+/* The CPU ID is encoded in the trap base register, 20 bits to the left of
+ * bit zero, with 2 bits being significant.
+ */
+#define TBR_ID_SHIFT 20
+
+static inline int get_cpuid(void)
+{
+ register int retval;
+ __asm__ __volatile__("rd %%tbr, %0\n\t"
+ "srl %0, %1, %0\n\t" :
+ "=r" (retval) :
+ "i" (TBR_ID_SHIFT));
+ return (retval & 3);
+}
+
+static inline int get_modid(void)
+{
+ return (get_cpuid() | 0x8);
+}
+
+
+#endif /* !(_SPARC_MBUS_H) */
diff --git a/arch/sparc/include/asm/mc146818rtc.h b/arch/sparc/include/asm/mc146818rtc.h
new file mode 100644
index 000000000..07faf754e
--- /dev/null
+++ b/arch/sparc/include/asm/mc146818rtc.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_MC146818RTC_H
+#define ___ASM_SPARC_MC146818RTC_H
+
+#include <linux/spinlock.h>
+
+extern spinlock_t rtc_lock;
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/mc146818rtc_64.h>
+#else
+#include <asm/mc146818rtc_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/mc146818rtc_32.h b/arch/sparc/include/asm/mc146818rtc_32.h
new file mode 100644
index 000000000..d8fd75da8
--- /dev/null
+++ b/arch/sparc/include/asm/mc146818rtc_32.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_SPARC_MC146818RTC_H
+#define __ASM_SPARC_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#define RTC_IRQ 8
+
+#endif /* __ASM_SPARC_MC146818RTC_H */
diff --git a/arch/sparc/include/asm/mc146818rtc_64.h b/arch/sparc/include/asm/mc146818rtc_64.h
new file mode 100644
index 000000000..b1708a7e5
--- /dev/null
+++ b/arch/sparc/include/asm/mc146818rtc_64.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_SPARC64_MC146818RTC_H
+#define __ASM_SPARC64_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+extern unsigned long cmos_regs;
+#define RTC_PORT(x) (cmos_regs + (x))
+#define RTC_ALWAYS_BCD 0
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#endif /* __ASM_SPARC64_MC146818RTC_H */
diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h
new file mode 100644
index 000000000..ec31a06d0
--- /dev/null
+++ b/arch/sparc/include/asm/mdesc.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_MDESC_H
+#define _SPARC64_MDESC_H
+
+#include <linux/types.h>
+#include <linux/cpumask.h>
+#include <asm/prom.h>
+
+struct mdesc_handle;
+
+/* Machine description operations are to be surrounded by grab and
+ * release calls. The mdesc_handle returned from the grab is
+ * the first argument to all of the operational calls that work
+ * on mdescs.
+ */
+struct mdesc_handle *mdesc_grab(void);
+void mdesc_release(struct mdesc_handle *);
+
+#define MDESC_NODE_NULL (~(u64)0)
+#define MDESC_MAX_STR_LEN 256
+
+u64 mdesc_node_by_name(struct mdesc_handle *handle,
+ u64 from_node, const char *name);
+#define mdesc_for_each_node_by_name(__hdl, __node, __name) \
+ for (__node = mdesc_node_by_name(__hdl, MDESC_NODE_NULL, __name); \
+ (__node) != MDESC_NODE_NULL; \
+ __node = mdesc_node_by_name(__hdl, __node, __name))
+
+/* Access to property values returned from mdesc_get_property() are
+ * only valid inside of a mdesc_grab()/mdesc_release() sequence.
+ * Once mdesc_release() is called, the memory backed up by these
+ * pointers may reference freed up memory.
+ *
+ * Therefore callers must make copies of any property values
+ * they need.
+ *
+ * These same rules apply to mdesc_node_name().
+ */
+const void *mdesc_get_property(struct mdesc_handle *handle,
+ u64 node, const char *name, int *lenp);
+const char *mdesc_node_name(struct mdesc_handle *hp, u64 node);
+
+/* MD arc iteration, the standard sequence is:
+ *
+ * unsigned long arc;
+ * mdesc_for_each_arc(arc, handle, node, MDESC_ARC_TYPE_{FWD,BACK}) {
+ * unsigned long target = mdesc_arc_target(handle, arc);
+ * ...
+ * }
+ */
+
+#define MDESC_ARC_TYPE_FWD "fwd"
+#define MDESC_ARC_TYPE_BACK "back"
+
+u64 mdesc_next_arc(struct mdesc_handle *handle, u64 from,
+ const char *arc_type);
+#define mdesc_for_each_arc(__arc, __hdl, __node, __type) \
+ for (__arc = mdesc_next_arc(__hdl, __node, __type); \
+ (__arc) != MDESC_NODE_NULL; \
+ __arc = mdesc_next_arc(__hdl, __arc, __type))
+
+u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc);
+
+void mdesc_update(void);
+
+struct mdesc_notifier_client {
+ void (*add)(struct mdesc_handle *handle, u64 node,
+ const char *node_name);
+ void (*remove)(struct mdesc_handle *handle, u64 node,
+ const char *node_name);
+ const char *node_name;
+ struct mdesc_notifier_client *next;
+};
+
+void mdesc_register_notifier(struct mdesc_notifier_client *client);
+
+union md_node_info {
+ struct vdev_port {
+ u64 id; /* id */
+ u64 parent_cfg_hdl; /* parent config handle */
+ const char *name; /* name (property) */
+ } vdev_port;
+ struct ds_port {
+ u64 id; /* id */
+ } ds_port;
+};
+
+u64 mdesc_get_node(struct mdesc_handle *hp, const char *node_name,
+ union md_node_info *node_info);
+int mdesc_get_node_info(struct mdesc_handle *hp, u64 node,
+ const char *node_name, union md_node_info *node_info);
+
+void mdesc_fill_in_cpu_data(cpumask_t *mask);
+void mdesc_populate_present_mask(cpumask_t *mask);
+void mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask);
+
+void sun4v_mdesc_init(void);
+
+#endif
diff --git a/arch/sparc/include/asm/memctrl.h b/arch/sparc/include/asm/memctrl.h
new file mode 100644
index 000000000..6790ed608
--- /dev/null
+++ b/arch/sparc/include/asm/memctrl.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_MEMCTRL_H
+#define _SPARC_MEMCTRL_H
+
+typedef int (*dimm_printer_t)(int synd_code, unsigned long paddr, char *buf, int buflen);
+
+int register_dimm_printer(dimm_printer_t func);
+void unregister_dimm_printer(dimm_printer_t func);
+
+#endif /* _SPARC_MEMCTRL_H */
diff --git a/arch/sparc/include/asm/mman.h b/arch/sparc/include/asm/mman.h
new file mode 100644
index 000000000..af9c10c83
--- /dev/null
+++ b/arch/sparc/include/asm/mman.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_MMAN_H__
+#define __SPARC_MMAN_H__
+
+#include <uapi/asm/mman.h>
+
+#ifndef __ASSEMBLY__
+#define arch_mmap_check(addr,len,flags) sparc_mmap_check(addr,len)
+int sparc_mmap_check(unsigned long addr, unsigned long len);
+
+#ifdef CONFIG_SPARC64
+#include <asm/adi_64.h>
+
+static inline void ipi_set_tstate_mcde(void *arg)
+{
+ struct mm_struct *mm = arg;
+
+ /* Set TSTATE_MCDE for the task using address map that ADI has been
+ * enabled on if the task is running. If not, it will be set
+ * automatically at the next context switch
+ */
+ if (current->mm == mm) {
+ struct pt_regs *regs;
+
+ regs = task_pt_regs(current);
+ regs->tstate |= TSTATE_MCDE;
+ }
+}
+
+#define arch_calc_vm_prot_bits(prot, pkey) sparc_calc_vm_prot_bits(prot)
+static inline unsigned long sparc_calc_vm_prot_bits(unsigned long prot)
+{
+ if (adi_capable() && (prot & PROT_ADI)) {
+ struct pt_regs *regs;
+
+ if (!current->mm->context.adi) {
+ regs = task_pt_regs(current);
+ regs->tstate |= TSTATE_MCDE;
+ current->mm->context.adi = true;
+ on_each_cpu_mask(mm_cpumask(current->mm),
+ ipi_set_tstate_mcde, current->mm, 0);
+ }
+ return VM_SPARC_ADI;
+ } else {
+ return 0;
+ }
+}
+
+#define arch_validate_prot(prot, addr) sparc_validate_prot(prot, addr)
+static inline int sparc_validate_prot(unsigned long prot, unsigned long addr)
+{
+ if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI))
+ return 0;
+ return 1;
+}
+
+#define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags)
+/* arch_validate_flags() - Ensure combination of flags is valid for a
+ * VMA.
+ */
+static inline bool arch_validate_flags(unsigned long vm_flags)
+{
+ /* If ADI is being enabled on this VMA, check for ADI
+ * capability on the platform and ensure VMA is suitable
+ * for ADI
+ */
+ if (vm_flags & VM_SPARC_ADI) {
+ if (!adi_capable())
+ return false;
+
+ /* ADI can not be enabled on PFN mapped pages */
+ if (vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
+ return false;
+
+ /* Mergeable pages can become unmergeable
+ * if ADI is enabled on them even if they
+ * have identical data on them. This can be
+ * because ADI enabled pages with identical
+ * data may still not have identical ADI
+ * tags on them. Disallow ADI on mergeable
+ * pages.
+ */
+ if (vm_flags & VM_MERGEABLE)
+ return false;
+ }
+ return true;
+}
+#endif /* CONFIG_SPARC64 */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __SPARC_MMAN_H__ */
diff --git a/arch/sparc/include/asm/mmu.h b/arch/sparc/include/asm/mmu.h
new file mode 100644
index 000000000..286457e58
--- /dev/null
+++ b/arch/sparc/include/asm/mmu.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_MMU_H
+#define ___ASM_SPARC_MMU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/mmu_64.h>
+#else
+#include <asm/mmu_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/mmu_32.h b/arch/sparc/include/asm/mmu_32.h
new file mode 100644
index 000000000..d5b220ca7
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_32.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __MMU_H
+#define __MMU_H
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+/* mm/srmmu.c */
+extern ctxd_t *srmmu_ctx_table_phys;
+
+#endif
diff --git a/arch/sparc/include/asm/mmu_64.h b/arch/sparc/include/asm/mmu_64.h
new file mode 100644
index 000000000..7e2704c77
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_64.h
@@ -0,0 +1,129 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __MMU_H
+#define __MMU_H
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/hypervisor.h>
+
+#define CTX_NR_BITS 13
+
+#define TAG_CONTEXT_BITS ((_AC(1,UL) << CTX_NR_BITS) - _AC(1,UL))
+
+/* UltraSPARC-III+ and later have a feature whereby you can
+ * select what page size the various Data-TLB instances in the
+ * chip. In order to gracefully support this, we put the version
+ * field in a spot outside of the areas of the context register
+ * where this parameter is specified.
+ */
+#define CTX_VERSION_SHIFT 22
+#define CTX_VERSION_MASK ((~0UL) << CTX_VERSION_SHIFT)
+
+#define CTX_PGSZ_8KB _AC(0x0,UL)
+#define CTX_PGSZ_64KB _AC(0x1,UL)
+#define CTX_PGSZ_512KB _AC(0x2,UL)
+#define CTX_PGSZ_4MB _AC(0x3,UL)
+#define CTX_PGSZ_BITS _AC(0x7,UL)
+#define CTX_PGSZ0_NUC_SHIFT 61
+#define CTX_PGSZ1_NUC_SHIFT 58
+#define CTX_PGSZ0_SHIFT 16
+#define CTX_PGSZ1_SHIFT 19
+#define CTX_PGSZ_MASK ((CTX_PGSZ_BITS << CTX_PGSZ0_SHIFT) | \
+ (CTX_PGSZ_BITS << CTX_PGSZ1_SHIFT))
+
+#define CTX_PGSZ_BASE CTX_PGSZ_8KB
+#define CTX_PGSZ_HUGE CTX_PGSZ_4MB
+#define CTX_PGSZ_KERN CTX_PGSZ_4MB
+
+/* Thus, when running on UltraSPARC-III+ and later, we use the following
+ * PRIMARY_CONTEXT register values for the kernel context.
+ */
+#define CTX_CHEETAH_PLUS_NUC \
+ ((CTX_PGSZ_KERN << CTX_PGSZ0_NUC_SHIFT) | \
+ (CTX_PGSZ_BASE << CTX_PGSZ1_NUC_SHIFT))
+
+#define CTX_CHEETAH_PLUS_CTX0 \
+ ((CTX_PGSZ_KERN << CTX_PGSZ0_SHIFT) | \
+ (CTX_PGSZ_BASE << CTX_PGSZ1_SHIFT))
+
+/* If you want "the TLB context number" use CTX_NR_MASK. If you
+ * want "the bits I program into the context registers" use
+ * CTX_HW_MASK.
+ */
+#define CTX_NR_MASK TAG_CONTEXT_BITS
+#define CTX_HW_MASK (CTX_NR_MASK | CTX_PGSZ_MASK)
+
+#define CTX_FIRST_VERSION BIT(CTX_VERSION_SHIFT)
+#define CTX_VALID(__ctx) \
+ (!(((__ctx.sparc64_ctx_val) ^ tlb_context_cache) & CTX_VERSION_MASK))
+#define CTX_HWBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_HW_MASK)
+#define CTX_NRBITS(__ctx) ((__ctx.sparc64_ctx_val) & CTX_NR_MASK)
+
+#ifndef __ASSEMBLY__
+
+#define TSB_ENTRY_ALIGNMENT 16
+
+struct tsb {
+ unsigned long tag;
+ unsigned long pte;
+} __attribute__((aligned(TSB_ENTRY_ALIGNMENT)));
+
+void __tsb_insert(unsigned long ent, unsigned long tag, unsigned long pte);
+void tsb_flush(unsigned long ent, unsigned long tag);
+void tsb_init(struct tsb *tsb, unsigned long size);
+
+struct tsb_config {
+ struct tsb *tsb;
+ unsigned long tsb_rss_limit;
+ unsigned long tsb_nentries;
+ unsigned long tsb_reg_val;
+ unsigned long tsb_map_vaddr;
+ unsigned long tsb_map_pte;
+};
+
+#define MM_TSB_BASE 0
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+#define MM_TSB_HUGE 1
+#define MM_NUM_TSBS 2
+#else
+#define MM_NUM_TSBS 1
+#endif
+
+/* ADI tags are stored when a page is swapped out and the storage for
+ * tags is allocated dynamically. There is a tag storage descriptor
+ * associated with each set of tag storage pages. Tag storage descriptors
+ * are allocated dynamically. Since kernel will allocate a full page for
+ * each tag storage descriptor, we can store up to
+ * PAGE_SIZE/sizeof(tag storage descriptor) descriptors on that page.
+ */
+typedef struct {
+ unsigned long start; /* Start address for this tag storage */
+ unsigned long end; /* Last address for tag storage */
+ unsigned char *tags; /* Where the tags are */
+ unsigned long tag_users; /* number of references to descriptor */
+} tag_storage_desc_t;
+
+typedef struct {
+ spinlock_t lock;
+ unsigned long sparc64_ctx_val;
+ unsigned long hugetlb_pte_count;
+ unsigned long thp_pte_count;
+ struct tsb_config tsb_block[MM_NUM_TSBS];
+ struct hv_tsb_descr tsb_descr[MM_NUM_TSBS];
+ void *vdso;
+ bool adi;
+ tag_storage_desc_t *tag_store;
+ spinlock_t tag_lock;
+} mm_context_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#define TSB_CONFIG_TSB 0x00
+#define TSB_CONFIG_RSS_LIMIT 0x08
+#define TSB_CONFIG_NENTRIES 0x10
+#define TSB_CONFIG_REG_VAL 0x18
+#define TSB_CONFIG_MAP_VADDR 0x20
+#define TSB_CONFIG_MAP_PTE 0x28
+
+#endif /* __MMU_H */
diff --git a/arch/sparc/include/asm/mmu_context.h b/arch/sparc/include/asm/mmu_context.h
new file mode 100644
index 000000000..5e1ea3851
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_context.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_MMU_CONTEXT_H
+#define ___ASM_SPARC_MMU_CONTEXT_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/mmu_context_64.h>
+#else
+#include <asm/mmu_context_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/mmu_context_32.h b/arch/sparc/include/asm/mmu_context_32.h
new file mode 100644
index 000000000..509043f81
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_context_32.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_MMU_CONTEXT_H
+#define __SPARC_MMU_CONTEXT_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm-generic/mm_hooks.h>
+
+/* Initialize a new mmu context. This is invoked when a new
+ * address space instance (unique or shared) is instantiated.
+ */
+#define init_new_context init_new_context
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+
+/* Destroy a dead context. This occurs when mmput drops the
+ * mm_users count to zero, the mmaps have been released, and
+ * all the page tables have been flushed. Our job is to destroy
+ * any remaining processor-specific state.
+ */
+#define destroy_context destroy_context
+void destroy_context(struct mm_struct *mm);
+
+/* Switch the current MM context. */
+void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
+ struct task_struct *tsk);
+
+/* Activate a new MM instance for the current task. */
+#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL)
+
+#include <asm-generic/mmu_context.h>
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_MMU_CONTEXT_H) */
diff --git a/arch/sparc/include/asm/mmu_context_64.h b/arch/sparc/include/asm/mmu_context_64.h
new file mode 100644
index 000000000..799e797c5
--- /dev/null
+++ b/arch/sparc/include/asm/mmu_context_64.h
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC64_MMU_CONTEXT_H
+#define __SPARC64_MMU_CONTEXT_H
+
+/* Derived heavily from Linus's Alpha/AXP ASN code... */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/spinlock.h>
+#include <linux/mm_types.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+
+#include <asm/spitfire.h>
+#include <asm/adi_64.h>
+#include <asm-generic/mm_hooks.h>
+#include <asm/percpu.h>
+
+extern spinlock_t ctx_alloc_lock;
+extern unsigned long tlb_context_cache;
+extern unsigned long mmu_context_bmap[];
+
+DECLARE_PER_CPU(struct mm_struct *, per_cpu_secondary_mm);
+void get_new_mmu_context(struct mm_struct *mm);
+
+#define init_new_context init_new_context
+int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+#define destroy_context destroy_context
+void destroy_context(struct mm_struct *mm);
+
+void __tsb_context_switch(unsigned long pgd_pa,
+ struct tsb_config *tsb_base,
+ struct tsb_config *tsb_huge,
+ unsigned long tsb_descr_pa,
+ unsigned long secondary_ctx);
+
+static inline void tsb_context_switch_ctx(struct mm_struct *mm,
+ unsigned long ctx)
+{
+ __tsb_context_switch(__pa(mm->pgd),
+ &mm->context.tsb_block[MM_TSB_BASE],
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+ (mm->context.tsb_block[MM_TSB_HUGE].tsb ?
+ &mm->context.tsb_block[MM_TSB_HUGE] :
+ NULL)
+#else
+ NULL
+#endif
+ , __pa(&mm->context.tsb_descr[MM_TSB_BASE]),
+ ctx);
+}
+
+#define tsb_context_switch(X) tsb_context_switch_ctx(X, 0)
+
+void tsb_grow(struct mm_struct *mm,
+ unsigned long tsb_index,
+ unsigned long mm_rss);
+#ifdef CONFIG_SMP
+void smp_tsb_sync(struct mm_struct *mm);
+#else
+#define smp_tsb_sync(__mm) do { } while (0)
+#endif
+
+/* Set MMU context in the actual hardware. */
+#define load_secondary_context(__mm) \
+ __asm__ __volatile__( \
+ "\n661: stxa %0, [%1] %2\n" \
+ " .section .sun4v_1insn_patch, \"ax\"\n" \
+ " .word 661b\n" \
+ " stxa %0, [%1] %3\n" \
+ " .previous\n" \
+ " flush %%g6\n" \
+ : /* No outputs */ \
+ : "r" (CTX_HWBITS((__mm)->context)), \
+ "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU), "i" (ASI_MMU))
+
+void __flush_tlb_mm(unsigned long, unsigned long);
+
+/* Switch the current MM context. */
+static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
+{
+ unsigned long ctx_valid, flags;
+ int cpu = smp_processor_id();
+
+ per_cpu(per_cpu_secondary_mm, cpu) = mm;
+ if (unlikely(mm == &init_mm))
+ return;
+
+ spin_lock_irqsave(&mm->context.lock, flags);
+ ctx_valid = CTX_VALID(mm->context);
+ if (!ctx_valid)
+ get_new_mmu_context(mm);
+
+ /* We have to be extremely careful here or else we will miss
+ * a TSB grow if we switch back and forth between a kernel
+ * thread and an address space which has it's TSB size increased
+ * on another processor.
+ *
+ * It is possible to play some games in order to optimize the
+ * switch, but the safest thing to do is to unconditionally
+ * perform the secondary context load and the TSB context switch.
+ *
+ * For reference the bad case is, for address space "A":
+ *
+ * CPU 0 CPU 1
+ * run address space A
+ * set cpu0's bits in cpu_vm_mask
+ * switch to kernel thread, borrow
+ * address space A via entry_lazy_tlb
+ * run address space A
+ * set cpu1's bit in cpu_vm_mask
+ * flush_tlb_pending()
+ * reset cpu_vm_mask to just cpu1
+ * TSB grow
+ * run address space A
+ * context was valid, so skip
+ * TSB context switch
+ *
+ * At that point cpu0 continues to use a stale TSB, the one from
+ * before the TSB grow performed on cpu1. cpu1 did not cross-call
+ * cpu0 to update it's TSB because at that point the cpu_vm_mask
+ * only had cpu1 set in it.
+ */
+ tsb_context_switch_ctx(mm, CTX_HWBITS(mm->context));
+
+ /* Any time a processor runs a context on an address space
+ * for the first time, we must flush that context out of the
+ * local TLB.
+ */
+ if (!ctx_valid || !cpumask_test_cpu(cpu, mm_cpumask(mm))) {
+ cpumask_set_cpu(cpu, mm_cpumask(mm));
+ __flush_tlb_mm(CTX_HWBITS(mm->context),
+ SECONDARY_CONTEXT);
+ }
+ spin_unlock_irqrestore(&mm->context.lock, flags);
+}
+
+#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, NULL)
+
+#define __HAVE_ARCH_START_CONTEXT_SWITCH
+static inline void arch_start_context_switch(struct task_struct *prev)
+{
+ /* Save the current state of MCDPER register for the process
+ * we are switching from
+ */
+ if (adi_capable()) {
+ register unsigned long tmp_mcdper;
+
+ __asm__ __volatile__(
+ ".word 0x83438000\n\t" /* rd %mcdper, %g1 */
+ "mov %%g1, %0\n\t"
+ : "=r" (tmp_mcdper)
+ :
+ : "g1");
+ if (tmp_mcdper)
+ set_tsk_thread_flag(prev, TIF_MCDPER);
+ else
+ clear_tsk_thread_flag(prev, TIF_MCDPER);
+ }
+}
+
+#define finish_arch_post_lock_switch finish_arch_post_lock_switch
+static inline void finish_arch_post_lock_switch(void)
+{
+ /* Restore the state of MCDPER register for the new process
+ * just switched to.
+ */
+ if (adi_capable()) {
+ register unsigned long tmp_mcdper;
+
+ tmp_mcdper = test_thread_flag(TIF_MCDPER);
+ __asm__ __volatile__(
+ "mov %0, %%g1\n\t"
+ ".word 0x9d800001\n\t" /* wr %g0, %g1, %mcdper" */
+ ".word 0xaf902001\n\t" /* wrpr %g0, 1, %pmcdper */
+ :
+ : "ir" (tmp_mcdper)
+ : "g1");
+ if (current && current->mm && current->mm->context.adi) {
+ struct pt_regs *regs;
+
+ regs = task_pt_regs(current);
+ regs->tstate |= TSTATE_MCDE;
+ }
+ }
+}
+
+#define mm_untag_mask mm_untag_mask
+static inline unsigned long mm_untag_mask(struct mm_struct *mm)
+{
+ return -1UL >> adi_nbits();
+}
+
+#include <asm-generic/mmu_context.h>
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_MMU_CONTEXT_H) */
diff --git a/arch/sparc/include/asm/mmzone.h b/arch/sparc/include/asm/mmzone.h
new file mode 100644
index 000000000..a236d8aa8
--- /dev/null
+++ b/arch/sparc/include/asm/mmzone.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_MMZONE_H
+#define _SPARC64_MMZONE_H
+
+#ifdef CONFIG_NUMA
+
+#include <linux/cpumask.h>
+
+extern struct pglist_data *node_data[];
+
+#define NODE_DATA(nid) (node_data[nid])
+
+extern int numa_cpu_lookup_table[];
+extern cpumask_t numa_cpumask_lookup_table[];
+
+#endif /* CONFIG_NUMA */
+
+#endif /* _SPARC64_MMZONE_H */
diff --git a/arch/sparc/include/asm/mxcc.h b/arch/sparc/include/asm/mxcc.h
new file mode 100644
index 000000000..3a2561bea
--- /dev/null
+++ b/arch/sparc/include/asm/mxcc.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mxcc.h: Definitions of the Viking MXCC registers
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_MXCC_H
+#define _SPARC_MXCC_H
+
+/* These registers are accessed through ASI 0x2. */
+#define MXCC_DATSTREAM 0x1C00000 /* Data stream register */
+#define MXCC_SRCSTREAM 0x1C00100 /* Source stream register */
+#define MXCC_DESSTREAM 0x1C00200 /* Destination stream register */
+#define MXCC_RMCOUNT 0x1C00300 /* Count of references and misses */
+#define MXCC_STEST 0x1C00804 /* Internal self-test */
+#define MXCC_CREG 0x1C00A04 /* Control register */
+#define MXCC_SREG 0x1C00B00 /* Status register */
+#define MXCC_RREG 0x1C00C04 /* Reset register */
+#define MXCC_EREG 0x1C00E00 /* Error code register */
+#define MXCC_PREG 0x1C00F04 /* Address port register */
+
+/* Some MXCC constants. */
+#define MXCC_STREAM_SIZE 0x20 /* Size in bytes of one stream r/w */
+
+/* The MXCC Control Register:
+ *
+ * ----------------------------------------------------------------------
+ * | | RRC | RSV |PRE|MCE|PARE|ECE|RSV|
+ * ----------------------------------------------------------------------
+ * 31 10 9 8-6 5 4 3 2 1-0
+ *
+ * RRC: Controls what you read from MXCC_RMCOUNT reg.
+ * 0=Misses 1=References
+ * PRE: Prefetch enable
+ * MCE: Multiple Command Enable
+ * PARE: Parity enable
+ * ECE: External cache enable
+ */
+
+#define MXCC_CTL_RRC 0x00000200
+#define MXCC_CTL_PRE 0x00000020
+#define MXCC_CTL_MCE 0x00000010
+#define MXCC_CTL_PARE 0x00000008
+#define MXCC_CTL_ECE 0x00000004
+
+/* The MXCC Error Register:
+ *
+ * --------------------------------------------------------
+ * |ME| RSV|CE|PEW|PEE|ASE|EIV| MOPC|ECODE|PRIV|RSV|HPADDR|
+ * --------------------------------------------------------
+ * 31 30 29 28 27 26 25 24-15 14-7 6 5-3 2-0
+ *
+ * ME: Multiple Errors have occurred
+ * CE: Cache consistency Error
+ * PEW: Parity Error during a Write operation
+ * PEE: Parity Error involving the External cache
+ * ASE: ASynchronous Error
+ * EIV: This register is toast
+ * MOPC: MXCC Operation Code for instance causing error
+ * ECODE: The Error CODE
+ * PRIV: A privileged mode error? 0=no 1=yes
+ * HPADDR: High PhysicalADDRess bits (35-32)
+ */
+
+#define MXCC_ERR_ME 0x80000000
+#define MXCC_ERR_CE 0x20000000
+#define MXCC_ERR_PEW 0x10000000
+#define MXCC_ERR_PEE 0x08000000
+#define MXCC_ERR_ASE 0x04000000
+#define MXCC_ERR_EIV 0x02000000
+#define MXCC_ERR_MOPC 0x01FF8000
+#define MXCC_ERR_ECODE 0x00007F80
+#define MXCC_ERR_PRIV 0x00000040
+#define MXCC_ERR_HPADDR 0x0000000f
+
+/* The MXCC Port register:
+ *
+ * -----------------------------------------------------
+ * | | MID | |
+ * -----------------------------------------------------
+ * 31 21 20-18 17 0
+ *
+ * MID: The moduleID of the cpu your read this from.
+ */
+
+#ifndef __ASSEMBLY__
+
+static inline void mxcc_set_stream_src(unsigned long *paddr)
+{
+ unsigned long data0 = paddr[0];
+ unsigned long data1 = paddr[1];
+
+ __asm__ __volatile__ ("or %%g0, %0, %%g2\n\t"
+ "or %%g0, %1, %%g3\n\t"
+ "stda %%g2, [%2] %3\n\t" : :
+ "r" (data0), "r" (data1),
+ "r" (MXCC_SRCSTREAM),
+ "i" (ASI_M_MXCC) : "g2", "g3");
+}
+
+static inline void mxcc_set_stream_dst(unsigned long *paddr)
+{
+ unsigned long data0 = paddr[0];
+ unsigned long data1 = paddr[1];
+
+ __asm__ __volatile__ ("or %%g0, %0, %%g2\n\t"
+ "or %%g0, %1, %%g3\n\t"
+ "stda %%g2, [%2] %3\n\t" : :
+ "r" (data0), "r" (data1),
+ "r" (MXCC_DESSTREAM),
+ "i" (ASI_M_MXCC) : "g2", "g3");
+}
+
+static inline unsigned long mxcc_get_creg(void)
+{
+ unsigned long mxcc_control;
+
+ __asm__ __volatile__("set 0xffffffff, %%g2\n\t"
+ "set 0xffffffff, %%g3\n\t"
+ "stda %%g2, [%1] %2\n\t"
+ "lda [%3] %2, %0\n\t" :
+ "=r" (mxcc_control) :
+ "r" (MXCC_EREG), "i" (ASI_M_MXCC),
+ "r" (MXCC_CREG) : "g2", "g3");
+ return mxcc_control;
+}
+
+static inline void mxcc_set_creg(unsigned long mxcc_control)
+{
+ __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
+ "r" (mxcc_control), "r" (MXCC_CREG),
+ "i" (ASI_M_MXCC));
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !(_SPARC_MXCC_H) */
diff --git a/arch/sparc/include/asm/nmi.h b/arch/sparc/include/asm/nmi.h
new file mode 100644
index 000000000..920dc23f4
--- /dev/null
+++ b/arch/sparc/include/asm/nmi.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NMI_H
+#define __NMI_H
+
+int __init nmi_init(void);
+void perfctr_irq(int irq, struct pt_regs *regs);
+void nmi_adjust_hz(unsigned int new_hz);
+
+extern atomic_t nmi_active;
+
+void start_nmi_watchdog(void *unused);
+void stop_nmi_watchdog(void *unused);
+
+#endif /* __NMI_H */
diff --git a/arch/sparc/include/asm/ns87303.h b/arch/sparc/include/asm/ns87303.h
new file mode 100644
index 000000000..5401894a6
--- /dev/null
+++ b/arch/sparc/include/asm/ns87303.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* ns87303.h: Configuration Register Description for the
+ * National Semiconductor PC87303 (SuperIO).
+ *
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef _SPARC_NS87303_H
+#define _SPARC_NS87303_H 1
+
+/*
+ * Control Register Index Values
+ */
+#define FER 0x00
+#define FAR 0x01
+#define PTR 0x02
+#define FCR 0x03
+#define PCR 0x04
+#define KRR 0x05
+#define PMC 0x06
+#define TUP 0x07
+#define SID 0x08
+#define ASC 0x09
+#define CS0CF0 0x0a
+#define CS0CF1 0x0b
+#define CS1CF0 0x0c
+#define CS1CF1 0x0d
+
+/* Function Enable Register (FER) bits */
+#define FER_EDM 0x10 /* Encoded Drive and Motor pin information */
+
+/* Function Address Register (FAR) bits */
+#define FAR_LPT_MASK 0x03
+#define FAR_LPTB 0x00
+#define FAR_LPTA 0x01
+#define FAR_LPTC 0x02
+
+/* Power and Test Register (PTR) bits */
+#define PTR_LPTB_IRQ7 0x08
+#define PTR_LEVEL_IRQ 0x80 /* When not ECP/EPP: Use level IRQ */
+#define PTR_LPT_REG_DIR 0x80 /* When ECP/EPP: LPT CTR controls direction */
+ /* of the parallel port */
+
+/* Function Control Register (FCR) bits */
+#define FCR_LDE 0x10 /* Logical Drive Exchange */
+#define FCR_ZWS_ENA 0x20 /* Enable short host read/write in ECP/EPP */
+
+/* Printer Control Register (PCR) bits */
+#define PCR_EPP_ENABLE 0x01
+#define PCR_EPP_IEEE 0x02 /* Enable EPP Version 1.9 (IEEE 1284) */
+#define PCR_ECP_ENABLE 0x04
+#define PCR_ECP_CLK_ENA 0x08 /* If 0 ECP Clock is stopped on Power down */
+#define PCR_IRQ_POLAR 0x20 /* If 0 IRQ is level high or negative pulse, */
+ /* if 1 polarity is inverted */
+#define PCR_IRQ_ODRAIN 0x40 /* If 1, IRQ is open drain */
+
+/* Tape UARTs and Parallel Port Config Register (TUP) bits */
+#define TUP_EPP_TIMO 0x02 /* Enable EPP timeout IRQ */
+
+/* Advanced SuperIO Config Register (ASC) bits */
+#define ASC_LPT_IRQ7 0x01 /* Always use IRQ7 for LPT */
+#define ASC_DRV2_SEL 0x02 /* Logical Drive Exchange controlled by TDR */
+
+#define FER_RESERVED 0x00
+#define FAR_RESERVED 0x00
+#define PTR_RESERVED 0x73
+#define FCR_RESERVED 0xc4
+#define PCR_RESERVED 0x10
+#define KRR_RESERVED 0x00
+#define PMC_RESERVED 0x98
+#define TUP_RESERVED 0xfb
+#define SIP_RESERVED 0x00
+#define ASC_RESERVED 0x18
+#define CS0CF0_RESERVED 0x00
+#define CS0CF1_RESERVED 0x08
+#define CS1CF0_RESERVED 0x00
+#define CS1CF1_RESERVED 0x08
+
+#ifdef __KERNEL__
+
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+
+extern spinlock_t ns87303_lock;
+
+static inline int ns87303_modify(unsigned long port, unsigned int index,
+ unsigned char clr, unsigned char set)
+{
+ static unsigned char reserved[] = {
+ FER_RESERVED, FAR_RESERVED, PTR_RESERVED, FCR_RESERVED,
+ PCR_RESERVED, KRR_RESERVED, PMC_RESERVED, TUP_RESERVED,
+ SIP_RESERVED, ASC_RESERVED, CS0CF0_RESERVED, CS0CF1_RESERVED,
+ CS1CF0_RESERVED, CS1CF1_RESERVED
+ };
+ unsigned long flags;
+ unsigned char value;
+
+ if (index > 0x0d)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ns87303_lock, flags);
+
+ outb(index, port);
+ value = inb(port + 1);
+ value &= ~(reserved[index] | clr);
+ value |= set;
+ outb(value, port + 1);
+ outb(value, port + 1);
+
+ spin_unlock_irqrestore(&ns87303_lock, flags);
+
+ return 0;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* !(_SPARC_NS87303_H) */
diff --git a/arch/sparc/include/asm/obio.h b/arch/sparc/include/asm/obio.h
new file mode 100644
index 000000000..1b151f738
--- /dev/null
+++ b/arch/sparc/include/asm/obio.h
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * obio.h: Some useful locations in 0xFXXXXXXXX PA obio space on sun4d.
+ *
+ * Copyright (C) 1997 Jakub Jelinek <jj@sunsite.mff.cuni.cz>
+ */
+
+#ifndef _SPARC_OBIO_H
+#define _SPARC_OBIO_H
+
+#include <asm/asi.h>
+
+/* This weird monster likes to use the very upper parts of
+ 36bit PA for these things :) */
+
+/* CSR space (for each XDBUS)
+ * ------------------------------------------------------------------------
+ * | 0xFE | DEVID | | XDBUS ID | |
+ * ------------------------------------------------------------------------
+ * 35 28 27 20 19 10 9 8 7 0
+ */
+
+#define CSR_BASE_ADDR 0xe0000000
+#define CSR_CPU_SHIFT (32 - 4 - 5)
+#define CSR_XDBUS_SHIFT 8
+
+#define CSR_BASE(cpu) (((CSR_BASE_ADDR >> CSR_CPU_SHIFT) + cpu) << CSR_CPU_SHIFT)
+
+/* ECSR space (not for each XDBUS)
+ * ------------------------------------------------------------------------
+ * | 0xF | DEVID[7:1] | |
+ * ------------------------------------------------------------------------
+ * 35 32 31 25 24 0
+ */
+
+#define ECSR_BASE_ADDR 0x00000000
+#define ECSR_CPU_SHIFT (32 - 5)
+#define ECSR_DEV_SHIFT (32 - 8)
+
+#define ECSR_BASE(cpu) ((cpu) << ECSR_CPU_SHIFT)
+#define ECSR_DEV_BASE(devid) ((devid) << ECSR_DEV_SHIFT)
+
+/* Bus Watcher */
+#define BW_LOCAL_BASE 0xfff00000
+
+#define BW_CID 0x00000000
+#define BW_DBUS_CTRL 0x00000008
+#define BW_DBUS_DATA 0x00000010
+#define BW_CTRL 0x00001000
+#define BW_INTR_TABLE 0x00001040
+#define BW_INTR_TABLE_CLEAR 0x00001080
+#define BW_PRESCALER 0x000010c0
+#define BW_PTIMER_LIMIT 0x00002000
+#define BW_PTIMER_COUNTER2 0x00002004
+#define BW_PTIMER_NDLIMIT 0x00002008
+#define BW_PTIMER_CTRL 0x0000200c
+#define BW_PTIMER_COUNTER 0x00002010
+#define BW_TIMER_LIMIT 0x00003000
+#define BW_TIMER_COUNTER2 0x00003004
+#define BW_TIMER_NDLIMIT 0x00003008
+#define BW_TIMER_CTRL 0x0000300c
+#define BW_TIMER_COUNTER 0x00003010
+
+/* BW Control */
+#define BW_CTRL_USER_TIMER 0x00000004 /* Is User Timer Free run enabled */
+
+/* Boot Bus */
+#define BB_LOCAL_BASE 0xf0000000
+
+#define BB_STAT1 0x00100000
+#define BB_STAT2 0x00120000
+#define BB_STAT3 0x00140000
+#define BB_LEDS 0x002e0000
+
+/* Bits in BB_STAT2 */
+#define BB_STAT2_AC_INTR 0x04 /* Aiee! 5ms and power is gone... */
+#define BB_STAT2_TMP_INTR 0x10 /* My Penguins are burning. Are you able to smell it? */
+#define BB_STAT2_FAN_INTR 0x20 /* My fan refuses to work */
+#define BB_STAT2_PWR_INTR 0x40 /* On SC2000, one of the two ACs died. Ok, we go on... */
+#define BB_STAT2_MASK (BB_STAT2_AC_INTR|BB_STAT2_TMP_INTR|BB_STAT2_FAN_INTR|BB_STAT2_PWR_INTR)
+
+/* Cache Controller */
+#define CC_BASE 0x1F00000
+#define CC_DATSTREAM 0x1F00000 /* Data stream register */
+#define CC_DATSIZE 0x1F0003F /* Size */
+#define CC_SRCSTREAM 0x1F00100 /* Source stream register */
+#define CC_DESSTREAM 0x1F00200 /* Destination stream register */
+#define CC_RMCOUNT 0x1F00300 /* Count of references and misses */
+#define CC_IPEN 0x1F00406 /* Pending Interrupts */
+#define CC_IMSK 0x1F00506 /* Interrupt Mask */
+#define CC_ICLR 0x1F00606 /* Clear pending Interrupts */
+#define CC_IGEN 0x1F00704 /* Generate Interrupt register */
+#define CC_STEST 0x1F00804 /* Internal self-test */
+#define CC_CREG 0x1F00A04 /* Control register */
+#define CC_SREG 0x1F00B00 /* Status register */
+#define CC_RREG 0x1F00C04 /* Reset register */
+#define CC_EREG 0x1F00E00 /* Error code register */
+#define CC_CID 0x1F00F04 /* Component ID */
+
+#ifndef __ASSEMBLY__
+
+static inline int bw_get_intr_mask(int sbus_level)
+{
+ int mask;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0" :
+ "=r" (mask) :
+ "r" (BW_LOCAL_BASE + BW_INTR_TABLE + (sbus_level << 3)),
+ "i" (ASI_M_CTL));
+ return mask;
+}
+
+static inline void bw_clear_intr_mask(int sbus_level, int mask)
+{
+ __asm__ __volatile__ ("stha %0, [%1] %2" : :
+ "r" (mask),
+ "r" (BW_LOCAL_BASE + BW_INTR_TABLE_CLEAR + (sbus_level << 3)),
+ "i" (ASI_M_CTL));
+}
+
+static inline unsigned int bw_get_prof_limit(int cpu)
+{
+ unsigned int limit;
+
+ __asm__ __volatile__ ("lda [%1] %2, %0" :
+ "=r" (limit) :
+ "r" (CSR_BASE(cpu) + BW_PTIMER_LIMIT),
+ "i" (ASI_M_CTL));
+ return limit;
+}
+
+static inline void bw_set_prof_limit(int cpu, unsigned int limit)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (limit),
+ "r" (CSR_BASE(cpu) + BW_PTIMER_LIMIT),
+ "i" (ASI_M_CTL));
+}
+
+static inline unsigned int bw_get_ctrl(int cpu)
+{
+ unsigned int ctrl;
+
+ __asm__ __volatile__ ("lda [%1] %2, %0" :
+ "=r" (ctrl) :
+ "r" (CSR_BASE(cpu) + BW_CTRL),
+ "i" (ASI_M_CTL));
+ return ctrl;
+}
+
+static inline void bw_set_ctrl(int cpu, unsigned int ctrl)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (ctrl),
+ "r" (CSR_BASE(cpu) + BW_CTRL),
+ "i" (ASI_M_CTL));
+}
+
+static inline unsigned int cc_get_ipen(void)
+{
+ unsigned int pending;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0" :
+ "=r" (pending) :
+ "r" (CC_IPEN),
+ "i" (ASI_M_MXCC));
+ return pending;
+}
+
+static inline void cc_set_iclr(unsigned int clear)
+{
+ __asm__ __volatile__ ("stha %0, [%1] %2" : :
+ "r" (clear),
+ "r" (CC_ICLR),
+ "i" (ASI_M_MXCC));
+}
+
+static inline unsigned int cc_get_imsk(void)
+{
+ unsigned int mask;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0" :
+ "=r" (mask) :
+ "r" (CC_IMSK),
+ "i" (ASI_M_MXCC));
+ return mask;
+}
+
+static inline void cc_set_imsk(unsigned int mask)
+{
+ __asm__ __volatile__ ("stha %0, [%1] %2" : :
+ "r" (mask),
+ "r" (CC_IMSK),
+ "i" (ASI_M_MXCC));
+}
+
+static inline unsigned int cc_get_imsk_other(int cpuid)
+{
+ unsigned int mask;
+
+ __asm__ __volatile__ ("lduha [%1] %2, %0" :
+ "=r" (mask) :
+ "r" (ECSR_BASE(cpuid) | CC_IMSK),
+ "i" (ASI_M_CTL));
+ return mask;
+}
+
+static inline void cc_set_imsk_other(int cpuid, unsigned int mask)
+{
+ __asm__ __volatile__ ("stha %0, [%1] %2" : :
+ "r" (mask),
+ "r" (ECSR_BASE(cpuid) | CC_IMSK),
+ "i" (ASI_M_CTL));
+}
+
+static inline void cc_set_igen(unsigned int gen)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (gen),
+ "r" (CC_IGEN),
+ "i" (ASI_M_MXCC));
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !(_SPARC_OBIO_H) */
diff --git a/arch/sparc/include/asm/openprom.h b/arch/sparc/include/asm/openprom.h
new file mode 100644
index 000000000..69545b3e5
--- /dev/null
+++ b/arch/sparc/include/asm/openprom.h
@@ -0,0 +1,280 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_OPENPROM_H
+#define __SPARC_OPENPROM_H
+
+/* openprom.h: Prom structures and defines for access to the OPENBOOT
+ * prom routines and data areas.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+/* Empirical constants... */
+#define LINUX_OPPROM_MAGIC 0x10010407
+
+#ifndef __ASSEMBLY__
+#include <linux/of.h>
+
+/* V0 prom device operations. */
+struct linux_dev_v0_funcs {
+ int (*v0_devopen)(char *device_str);
+ int (*v0_devclose)(int dev_desc);
+ int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+ int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+ int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+ int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
+};
+
+/* V2 and later prom device operations. */
+struct linux_dev_v2_funcs {
+ phandle (*v2_inst2pkg)(int d); /* Convert ihandle to phandle */
+ char * (*v2_dumb_mem_alloc)(char *va, unsigned int sz);
+ void (*v2_dumb_mem_free)(char *va, unsigned int sz);
+
+ /* To map devices into virtual I/O space. */
+ char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned int paddr, unsigned int sz);
+ void (*v2_dumb_munmap)(char *virta, unsigned int size);
+
+ int (*v2_dev_open)(char *devpath);
+ void (*v2_dev_close)(int d);
+ int (*v2_dev_read)(int d, char *buf, int nbytes);
+ int (*v2_dev_write)(int d, const char *buf, int nbytes);
+ int (*v2_dev_seek)(int d, int hi, int lo);
+
+ /* Never issued (multistage load support) */
+ void (*v2_wheee2)(void);
+ void (*v2_wheee3)(void);
+};
+
+struct linux_mlist_v0 {
+ struct linux_mlist_v0 *theres_more;
+ unsigned int start_adr;
+ unsigned int num_bytes;
+};
+
+struct linux_mem_v0 {
+ struct linux_mlist_v0 **v0_totphys;
+ struct linux_mlist_v0 **v0_prommap;
+ struct linux_mlist_v0 **v0_available; /* What we can use */
+};
+
+/* Arguments sent to the kernel from the boot prompt. */
+struct linux_arguments_v0 {
+ char *argv[8];
+ char args[100];
+ char boot_dev[2];
+ int boot_dev_ctrl;
+ int boot_dev_unit;
+ int dev_partition;
+ char *kernel_file_name;
+ void *aieee1; /* XXX */
+};
+
+/* V2 and up boot things. */
+struct linux_bootargs_v2 {
+ char **bootpath;
+ char **bootargs;
+ int *fd_stdin;
+ int *fd_stdout;
+};
+
+/* The top level PROM vector. */
+struct linux_romvec {
+ /* Version numbers. */
+ unsigned int pv_magic_cookie;
+ unsigned int pv_romvers;
+ unsigned int pv_plugin_revision;
+ unsigned int pv_printrev;
+
+ /* Version 0 memory descriptors. */
+ struct linux_mem_v0 pv_v0mem;
+
+ /* Node operations. */
+ struct linux_nodeops *pv_nodeops;
+
+ char **pv_bootstr;
+ struct linux_dev_v0_funcs pv_v0devops;
+
+ char *pv_stdin;
+ char *pv_stdout;
+#define PROMDEV_KBD 0 /* input from keyboard */
+#define PROMDEV_SCREEN 0 /* output to screen */
+#define PROMDEV_TTYA 1 /* in/out to ttya */
+#define PROMDEV_TTYB 2 /* in/out to ttyb */
+
+ /* Blocking getchar/putchar. NOT REENTRANT! (grr) */
+ int (*pv_getchar)(void);
+ void (*pv_putchar)(int ch);
+
+ /* Non-blocking variants. */
+ int (*pv_nbgetchar)(void);
+ int (*pv_nbputchar)(int ch);
+
+ void (*pv_putstr)(char *str, int len);
+
+ /* Miscellany. */
+ void (*pv_reboot)(char *bootstr);
+ void (*pv_printf)(__const__ char *fmt, ...);
+ void (*pv_abort)(void);
+ __volatile__ int *pv_ticks;
+ void (*pv_halt)(void);
+ void (**pv_synchook)(void);
+
+ /* Evaluate a forth string, not different proto for V0 and V2->up. */
+ union {
+ void (*v0_eval)(int len, char *str);
+ void (*v2_eval)(char *str);
+ } pv_fortheval;
+
+ struct linux_arguments_v0 **pv_v0bootargs;
+
+ /* Get ether address. */
+ unsigned int (*pv_enaddr)(int d, char *enaddr);
+
+ struct linux_bootargs_v2 pv_v2bootargs;
+ struct linux_dev_v2_funcs pv_v2devops;
+
+ int filler[15];
+
+ /* This one is sun4c/sun4 only. */
+ void (*pv_setctxt)(int ctxt, char *va, int pmeg);
+
+ /* Prom version 3 Multiprocessor routines. This stuff is crazy.
+ * No joke. Calling these when there is only one cpu probably
+ * crashes the machine, have to test this. :-)
+ */
+
+ /* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
+ * 'thiscontext' executing at address 'prog_counter'
+ */
+ int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
+ int thiscontext, char *prog_counter);
+
+ /* v3_cpustop() will cause cpu 'whichcpu' to stop executing
+ * until a resume cpu call is made.
+ */
+ int (*v3_cpustop)(unsigned int whichcpu);
+
+ /* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
+ * resume cpu call is made.
+ */
+ int (*v3_cpuidle)(unsigned int whichcpu);
+
+ /* v3_cpuresume() will resume processor 'whichcpu' executing
+ * starting with whatever 'pc' and 'npc' were left at the
+ * last 'idle' or 'stop' call.
+ */
+ int (*v3_cpuresume)(unsigned int whichcpu);
+};
+
+/* Routines for traversing the prom device tree. */
+struct linux_nodeops {
+ phandle (*no_nextnode)(phandle node);
+ phandle (*no_child)(phandle node);
+ int (*no_proplen)(phandle node, const char *name);
+ int (*no_getprop)(phandle node, const char *name, char *val);
+ int (*no_setprop)(phandle node, const char *name, char *val, int len);
+ char * (*no_nextprop)(phandle node, char *name);
+};
+
+/* More fun PROM structures for device probing. */
+#if defined(__sparc__) && defined(__arch64__)
+#define PROMREG_MAX 24
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 32
+#else
+#define PROMREG_MAX 16
+#define PROMVADDR_MAX 16
+#define PROMINTR_MAX 15
+#endif
+
+struct linux_prom_registers {
+ unsigned int which_io; /* hi part of physical address */
+ unsigned int phys_addr; /* The physical address of this register */
+ unsigned int reg_size; /* How many bytes does this register take up? */
+};
+
+struct linux_prom64_registers {
+ unsigned long phys_addr;
+ unsigned long reg_size;
+};
+
+struct linux_prom_irqs {
+ int pri; /* IRQ priority */
+ int vector; /* This is foobar, what does it do? */
+};
+
+/* Element of the "ranges" vector */
+struct linux_prom_ranges {
+ unsigned int ot_child_space;
+ unsigned int ot_child_base; /* Bus feels this */
+ unsigned int ot_parent_space;
+ unsigned int ot_parent_base; /* CPU looks from here */
+ unsigned int or_size;
+};
+
+/*
+ * Ranges and reg properties are a bit different for PCI.
+ */
+#if defined(__sparc__) && defined(__arch64__)
+struct linux_prom_pci_registers {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+#else
+struct linux_prom_pci_registers {
+ /*
+ * We don't know what information this field contain.
+ * We guess, PCI device function is in bits 15:8
+ * So, ...
+ */
+ unsigned int which_io; /* Let it be which_io */
+
+ unsigned int phys_hi;
+ unsigned int phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+#endif
+
+struct linux_prom_pci_ranges {
+ unsigned int child_phys_hi; /* Only certain bits are encoded here. */
+ unsigned int child_phys_mid;
+ unsigned int child_phys_lo;
+
+ unsigned int parent_phys_hi;
+ unsigned int parent_phys_lo;
+
+ unsigned int size_hi;
+ unsigned int size_lo;
+};
+
+struct linux_prom_pci_intmap {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+
+ unsigned int interrupt;
+
+ int cnode;
+ unsigned int cinterrupt;
+};
+
+struct linux_prom_pci_intmask {
+ unsigned int phys_hi;
+ unsigned int phys_mid;
+ unsigned int phys_lo;
+ unsigned int interrupt;
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_OPENPROM_H) */
diff --git a/arch/sparc/include/asm/oplib.h b/arch/sparc/include/asm/oplib.h
new file mode 100644
index 000000000..df49a7700
--- /dev/null
+++ b/arch/sparc/include/asm/oplib.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_OPLIB_H
+#define ___ASM_SPARC_OPLIB_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/oplib_64.h>
+#else
+#include <asm/oplib_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h
new file mode 100644
index 000000000..d1cf3a27a
--- /dev/null
+++ b/arch/sparc/include/asm/oplib_32.h
@@ -0,0 +1,184 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * oplib.h: Describes the interface and available routines in the
+ * Linux Prom library.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC_OPLIB_H
+#define __SPARC_OPLIB_H
+
+#include <asm/openprom.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+
+/* The master romvec pointer... */
+extern struct linux_romvec *romvec;
+
+/* Enumeration to describe the prom major version we have detected. */
+enum prom_major_version {
+ PROM_V0, /* Original sun4c V0 prom */
+ PROM_V2, /* sun4c and early sun4m V2 prom */
+ PROM_V3, /* sun4m and later, up to sun4d/sun4e machines V3 */
+ PROM_P1275, /* IEEE compliant ISA based Sun PROM, only sun4u */
+};
+
+extern enum prom_major_version prom_vers;
+/* Revision, and firmware revision. */
+extern unsigned int prom_rev, prom_prev;
+
+/* Root node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern phandle prom_root_node;
+
+/* Pointer to prom structure containing the device tree traversal
+ * and usage utility functions. Only prom-lib should use these,
+ * users use the interface defined by the library only!
+ */
+extern struct linux_nodeops *prom_nodeops;
+
+/* The functions... */
+
+/* You must call prom_init() before using any of the library services,
+ * preferably as early as possible. Pass it the romvec pointer.
+ */
+void prom_init(struct linux_romvec *rom_ptr);
+
+/* Boot argument acquisition, returns the boot command line string. */
+char *prom_getbootargs(void);
+
+/* Miscellaneous routines, don't really fit in any category per se. */
+
+/* Reboot the machine with the command line passed. */
+void prom_reboot(char *boot_command);
+
+/* Evaluate the forth string passed. */
+void prom_feval(char *forth_string);
+
+/* Enter the prom, with possibility of continuation with the 'go'
+ * command in newer proms.
+ */
+void prom_cmdline(void);
+
+/* Enter the prom, with no chance of continuation for the stand-alone
+ * which calls this.
+ */
+void __noreturn prom_halt(void);
+
+/* Set the PROM 'sync' callback function to the passed function pointer.
+ * When the user gives the 'sync' command at the prom prompt while the
+ * kernel is still active, the prom will call this routine.
+ *
+ * XXX The arguments are different on V0 vs. V2->higher proms, grrr! XXX
+ */
+typedef void (*sync_func_t)(void);
+void prom_setsync(sync_func_t func_ptr);
+
+/* Acquire the IDPROM of the root node in the prom device tree. This
+ * gets passed a buffer where you would like it stuffed. The return value
+ * is the format type of this idprom or 0xff on error.
+ */
+unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
+
+/* Get the prom major version. */
+int prom_version(void);
+
+/* Get the prom plugin revision. */
+int prom_getrev(void);
+
+/* Get the prom firmware revision. */
+int prom_getprev(void);
+
+/* Write a buffer of characters to the console. */
+void prom_console_write_buf(const char *buf, int len);
+
+/* Prom's internal routines, don't use in kernel/boot code. */
+__printf(1, 2) void prom_printf(const char *fmt, ...);
+void prom_write(const char *buf, unsigned int len);
+
+/* Multiprocessor operations... */
+
+/* Start the CPU with the given device tree node, context table, and context
+ * at the passed program counter.
+ */
+int prom_startcpu(int cpunode, struct linux_prom_registers *context_table,
+ int context, char *program_counter);
+
+/* Initialize the memory lists based upon the prom version. */
+void prom_meminit(void);
+
+/* PROM device tree traversal functions... */
+
+/* Get the child node of the given node, or zero if no child exists. */
+phandle prom_getchild(phandle parent_node);
+
+/* Get the next sibling node of the given node, or zero if no further
+ * siblings exist.
+ */
+phandle prom_getsibling(phandle node);
+
+/* Get the length, at the passed node, of the given property type.
+ * Returns -1 on error (ie. no such property at this node).
+ */
+int prom_getproplen(phandle thisnode, const char *property);
+
+/* Fetch the requested property using the given buffer. Returns
+ * the number of bytes the prom put into your buffer or -1 on error.
+ */
+int __must_check prom_getproperty(phandle thisnode, const char *property,
+ char *prop_buffer, int propbuf_size);
+
+/* Acquire an integer property. */
+int prom_getint(phandle node, char *property);
+
+/* Acquire an integer property, with a default value. */
+int prom_getintdefault(phandle node, char *property, int defval);
+
+/* Acquire a boolean property, 0=FALSE 1=TRUE. */
+int prom_getbool(phandle node, char *prop);
+
+/* Acquire a string property, null string on error. */
+void prom_getstring(phandle node, char *prop, char *buf, int bufsize);
+
+/* Search all siblings starting at the passed node for "name" matching
+ * the given string. Returns the node on success, zero on failure.
+ */
+phandle prom_searchsiblings(phandle node_start, char *name);
+
+/* Returns the next property after the passed property for the given
+ * node. Returns null string on failure.
+ */
+char *prom_nextprop(phandle node, char *prev_property, char *buffer);
+
+/* Returns phandle of the path specified */
+phandle prom_finddevice(char *name);
+
+/* Set the indicated property at the given node with the passed value.
+ * Returns the number of bytes of your value that the prom took.
+ */
+int prom_setprop(phandle node, const char *prop_name, char *prop_value,
+ int value_size);
+
+phandle prom_inst2pkg(int);
+
+/* Dorking with Bus ranges... */
+
+/* Apply promlib probes OBIO ranges to registers. */
+void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs);
+
+/* Apply ranges of any prom node (and optionally parent node as well) to registers. */
+void prom_apply_generic_ranges(phandle node, phandle parent,
+ struct linux_prom_registers *sbusregs, int nregs);
+
+void prom_ranges_init(void);
+
+/* CPU probing helpers. */
+int cpu_find_by_instance(int instance, phandle *prom_node, int *mid);
+int cpu_find_by_mid(int mid, phandle *prom_node);
+int cpu_get_hwmid(phandle prom_node);
+
+extern spinlock_t prom_lock;
+
+#endif /* !(__SPARC_OPLIB_H) */
diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h
new file mode 100644
index 000000000..a67abebd4
--- /dev/null
+++ b/arch/sparc/include/asm/oplib_64.h
@@ -0,0 +1,252 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* oplib.h: Describes the interface and available routines in the
+ * Linux Prom library.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef __SPARC64_OPLIB_H
+#define __SPARC64_OPLIB_H
+
+#include <asm/openprom.h>
+
+/* OBP version string. */
+extern char prom_version[];
+
+/* Root node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern phandle prom_root_node;
+
+/* PROM stdout */
+extern int prom_stdout;
+
+/* /chosen node of the prom device tree, this stays constant after
+ * initialization is complete.
+ */
+extern phandle prom_chosen_node;
+
+/* Helper values and strings in arch/sparc64/kernel/head.S */
+extern const char prom_peer_name[];
+extern const char prom_compatible_name[];
+extern const char prom_root_compatible[];
+extern const char prom_cpu_compatible[];
+extern const char prom_finddev_name[];
+extern const char prom_chosen_path[];
+extern const char prom_cpu_path[];
+extern const char prom_getprop_name[];
+extern const char prom_mmu_name[];
+extern const char prom_callmethod_name[];
+extern const char prom_translate_name[];
+extern const char prom_map_name[];
+extern const char prom_unmap_name[];
+extern int prom_mmu_ihandle_cache;
+extern unsigned int prom_boot_mapped_pc;
+extern unsigned int prom_boot_mapping_mode;
+extern unsigned long prom_boot_mapping_phys_high, prom_boot_mapping_phys_low;
+
+struct linux_mlist_p1275 {
+ struct linux_mlist_p1275 *theres_more;
+ unsigned long start_adr;
+ unsigned long num_bytes;
+};
+
+struct linux_mem_p1275 {
+ struct linux_mlist_p1275 **p1275_totphys;
+ struct linux_mlist_p1275 **p1275_prommap;
+ struct linux_mlist_p1275 **p1275_available; /* What we can use */
+};
+
+/* The functions... */
+
+/* You must call prom_init() before using any of the library services,
+ * preferably as early as possible. Pass it the romvec pointer.
+ */
+void prom_init(void *cif_handler);
+void prom_init_report(void);
+
+/* Boot argument acquisition, returns the boot command line string. */
+char *prom_getbootargs(void);
+
+/* Miscellaneous routines, don't really fit in any category per se. */
+
+/* Reboot the machine with the command line passed. */
+void prom_reboot(const char *boot_command);
+
+/* Evaluate the forth string passed. */
+void prom_feval(const char *forth_string);
+
+/* Enter the prom, with possibility of continuation with the 'go'
+ * command in newer proms.
+ */
+void prom_cmdline(void);
+
+/* Enter the prom, with no chance of continuation for the stand-alone
+ * which calls this.
+ */
+void prom_halt(void) __attribute__ ((noreturn));
+
+/* Halt and power-off the machine. */
+void prom_halt_power_off(void) __attribute__ ((noreturn));
+
+/* Acquire the IDPROM of the root node in the prom device tree. This
+ * gets passed a buffer where you would like it stuffed. The return value
+ * is the format type of this idprom or 0xff on error.
+ */
+unsigned char prom_get_idprom(char *idp_buffer, int idpbuf_size);
+
+/* Write a buffer of characters to the console. */
+void prom_console_write_buf(const char *buf, int len);
+
+/* Prom's internal routines, don't use in kernel/boot code. */
+__printf(1, 2) void prom_printf(const char *fmt, ...);
+void prom_write(const char *buf, unsigned int len);
+
+/* Multiprocessor operations... */
+#ifdef CONFIG_SMP
+/* Start the CPU with the given device tree node at the passed program
+ * counter with the given arg passed in via register %o0.
+ */
+void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg);
+
+/* Start the CPU with the given cpu ID at the passed program
+ * counter with the given arg passed in via register %o0.
+ */
+void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg);
+
+/* Stop the CPU with the given cpu ID. */
+void prom_stopcpu_cpuid(int cpuid);
+
+/* Stop the current CPU. */
+void prom_stopself(void);
+
+/* Idle the current CPU. */
+void prom_idleself(void);
+
+/* Resume the CPU with the passed device tree node. */
+void prom_resumecpu(int cpunode);
+#endif
+
+/* Power management interfaces. */
+
+/* Put the current CPU to sleep. */
+void prom_sleepself(void);
+
+/* Put the entire system to sleep. */
+int prom_sleepsystem(void);
+
+/* Initiate a wakeup event. */
+int prom_wakeupsystem(void);
+
+/* MMU and memory related OBP interfaces. */
+
+/* Get unique string identifying SIMM at given physical address. */
+int prom_getunumber(int syndrome_code,
+ unsigned long phys_addr,
+ char *buf, int buflen);
+
+/* Retain physical memory to the caller across soft resets. */
+int prom_retain(const char *name, unsigned long size,
+ unsigned long align, unsigned long *paddr);
+
+/* Load explicit I/D TLB entries into the calling processor. */
+long prom_itlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr);
+
+long prom_dtlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr);
+
+/* Map/Unmap client program address ranges. First the format of
+ * the mapping mode argument.
+ */
+#define PROM_MAP_WRITE 0x0001 /* Writable */
+#define PROM_MAP_READ 0x0002 /* Readable - sw */
+#define PROM_MAP_EXEC 0x0004 /* Executable - sw */
+#define PROM_MAP_LOCKED 0x0010 /* Locked, use i/dtlb load calls for this instead */
+#define PROM_MAP_CACHED 0x0020 /* Cacheable in both L1 and L2 caches */
+#define PROM_MAP_SE 0x0040 /* Side-Effects */
+#define PROM_MAP_GLOB 0x0080 /* Global */
+#define PROM_MAP_IE 0x0100 /* Invert-Endianness */
+#define PROM_MAP_DEFAULT (PROM_MAP_WRITE | PROM_MAP_READ | PROM_MAP_EXEC | PROM_MAP_CACHED)
+
+int prom_map(int mode, unsigned long size,
+ unsigned long vaddr, unsigned long paddr);
+void prom_unmap(unsigned long size, unsigned long vaddr);
+
+
+/* PROM device tree traversal functions... */
+
+/* Get the child node of the given node, or zero if no child exists. */
+phandle prom_getchild(phandle parent_node);
+
+/* Get the next sibling node of the given node, or zero if no further
+ * siblings exist.
+ */
+phandle prom_getsibling(phandle node);
+
+/* Get the length, at the passed node, of the given property type.
+ * Returns -1 on error (ie. no such property at this node).
+ */
+int prom_getproplen(phandle thisnode, const char *property);
+
+/* Fetch the requested property using the given buffer. Returns
+ * the number of bytes the prom put into your buffer or -1 on error.
+ */
+int prom_getproperty(phandle thisnode, const char *property,
+ char *prop_buffer, int propbuf_size);
+
+/* Acquire an integer property. */
+int prom_getint(phandle node, const char *property);
+
+/* Acquire an integer property, with a default value. */
+int prom_getintdefault(phandle node, const char *property, int defval);
+
+/* Acquire a boolean property, 0=FALSE 1=TRUE. */
+int prom_getbool(phandle node, const char *prop);
+
+/* Acquire a string property, null string on error. */
+void prom_getstring(phandle node, const char *prop, char *buf,
+ int bufsize);
+
+/* Does the passed node have the given "name"? YES=1 NO=0 */
+int prom_nodematch(phandle thisnode, const char *name);
+
+/* Search all siblings starting at the passed node for "name" matching
+ * the given string. Returns the node on success, zero on failure.
+ */
+phandle prom_searchsiblings(phandle node_start, const char *name);
+
+/* Return the first property type, as a string, for the given node.
+ * Returns a null string on error. Buffer should be at least 32B long.
+ */
+char *prom_firstprop(phandle node, char *buffer);
+
+/* Returns the next property after the passed property for the given
+ * node. Returns null string on failure. Buffer should be at least 32B long.
+ */
+char *prom_nextprop(phandle node, const char *prev_property, char *buf);
+
+/* Returns 1 if the specified node has given property. */
+int prom_node_has_property(phandle node, const char *property);
+
+/* Returns phandle of the path specified */
+phandle prom_finddevice(const char *name);
+
+/* Set the indicated property at the given node with the passed value.
+ * Returns the number of bytes of your value that the prom took.
+ */
+int prom_setprop(phandle node, const char *prop_name, char *prop_value,
+ int value_size);
+
+phandle prom_inst2pkg(int);
+void prom_sun4v_guest_soft_state(void);
+
+int prom_ihandle2path(int handle, char *buffer, int bufsize);
+
+/* Client interface level routines. */
+void p1275_cmd_direct(unsigned long *);
+
+#endif /* !(__SPARC64_OPLIB_H) */
diff --git a/arch/sparc/include/asm/page.h b/arch/sparc/include/asm/page.h
new file mode 100644
index 000000000..5e44cdf2a
--- /dev/null
+++ b/arch/sparc/include/asm/page.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_PAGE_H
+#define ___ASM_SPARC_PAGE_H
+
+#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/page_64.h>
+#else
+#include <asm/page_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h
new file mode 100644
index 000000000..6be6f683f
--- /dev/null
+++ b/arch/sparc/include/asm/page_32.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * page.h: Various defines and such for MMU operations on the Sparc for
+ * the Linux kernel.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_PAGE_H
+#define _SPARC_PAGE_H
+
+#include <linux/const.h>
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+#ifndef __ASSEMBLY__
+
+#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#define clear_user_page(addr, vaddr, page) \
+ do { clear_page(addr); \
+ sparc_flush_page_to_ram(page); \
+ } while (0)
+#define copy_user_page(to, from, vaddr, page) \
+ do { copy_page(to, from); \
+ sparc_flush_page_to_ram(page); \
+ } while (0)
+
+/* The following structure is used to hold the physical
+ * memory configuration of the machine. This is filled in
+ * prom_meminit() and is later used by mem_init() to set up
+ * mem_map[]. We statically allocate SPARC_PHYS_BANKS+1 of
+ * these structs, this is arbitrary. The entry after the
+ * last valid one has num_bytes==0.
+ */
+struct sparc_phys_banks {
+ unsigned long base_addr;
+ unsigned long num_bytes;
+};
+
+#define SPARC_PHYS_BANKS 32
+
+extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
+
+/* passing structs on the Sparc slow us down tremendously... */
+
+/* #define STRICT_MM_TYPECHECKS */
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long iopte; } iopte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long ctxd; } ctxd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+typedef struct { unsigned long iopgprot; } iopgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define iopte_val(x) ((x).iopte)
+#define pmd_val(x) ((x).pmd)
+#define pgd_val(x) ((x).pgd)
+#define ctxd_val(x) ((x).ctxd)
+#define pgprot_val(x) ((x).pgprot)
+#define iopgprot_val(x) ((x).iopgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { { (x) }, })
+#define __iopte(x) ((iopte_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __ctxd(x) ((ctxd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+#define __iopgprot(x) ((iopgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long iopte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long ctxd_t;
+typedef unsigned long pgprot_t;
+typedef unsigned long iopgprot_t;
+
+#define pte_val(x) (x)
+#define iopte_val(x) (x)
+#define pmd_val(x) (x)
+#define pgd_val(x) (x)
+#define ctxd_val(x) (x)
+#define pgprot_val(x) (x)
+#define iopgprot_val(x) (x)
+
+#define __pte(x) (x)
+#define __pmd(x) (x)
+#define __iopte(x) (x)
+#define __pgd(x) (x)
+#define __ctxd(x) (x)
+#define __pgprot(x) (x)
+#define __iopgprot(x) (x)
+
+#endif
+
+typedef pte_t *pgtable_t;
+
+#define TASK_UNMAPPED_BASE 0x50000000
+
+#else /* !(__ASSEMBLY__) */
+
+#define __pgprot(x) (x)
+
+#endif /* !(__ASSEMBLY__) */
+
+#define PAGE_OFFSET 0xf0000000
+#ifndef __ASSEMBLY__
+extern unsigned long phys_base;
+extern unsigned long pfn_base;
+#endif
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + phys_base)
+#define __va(x) ((void *)((unsigned long) (x) - phys_base + PAGE_OFFSET))
+
+#define virt_to_phys __pa
+#define phys_to_virt __va
+
+#define ARCH_PFN_OFFSET (pfn_base)
+#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+
+#define virt_addr_valid(kaddr) ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT) < max_mapnr)
+
+#include <asm-generic/memory_model.h>
+#include <asm-generic/getorder.h>
+
+#endif /* _SPARC_PAGE_H */
diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h
new file mode 100644
index 000000000..254dffd85
--- /dev/null
+++ b/arch/sparc/include/asm/page_64.h
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_PAGE_H
+#define _SPARC64_PAGE_H
+
+#include <linux/const.h>
+
+#define PAGE_SHIFT 13
+
+#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+/* Flushing for D-cache alias handling is only needed if
+ * the page size is smaller than 16K.
+ */
+#if PAGE_SHIFT < 14
+#define DCACHE_ALIASING_POSSIBLE
+#endif
+
+#define HPAGE_SHIFT 23
+#define REAL_HPAGE_SHIFT 22
+#define HPAGE_16GB_SHIFT 34
+#define HPAGE_2GB_SHIFT 31
+#define HPAGE_256MB_SHIFT 28
+#define HPAGE_64K_SHIFT 16
+#define REAL_HPAGE_SIZE (_AC(1,UL) << REAL_HPAGE_SHIFT)
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
+#define HPAGE_MASK (~(HPAGE_SIZE - 1UL))
+#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#define REAL_HPAGE_PER_HPAGE (_AC(1,UL) << (HPAGE_SHIFT - REAL_HPAGE_SHIFT))
+#define HUGE_MAX_HSTATE 5
+#endif
+
+#ifndef __ASSEMBLY__
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+struct pt_regs;
+void hugetlb_setup(struct pt_regs *regs);
+#endif
+
+#define WANT_PAGE_VIRTUAL
+
+void _clear_page(void *page);
+#define clear_page(X) _clear_page((void *)(X))
+struct page;
+void clear_user_page(void *addr, unsigned long vaddr, struct page *page);
+#define copy_page(X,Y) memcpy((void *)(X), (void *)(Y), PAGE_SIZE)
+void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *topage);
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
+struct vm_area_struct;
+void copy_user_highpage(struct page *to, struct page *from,
+ unsigned long vaddr, struct vm_area_struct *vma);
+#define __HAVE_ARCH_COPY_HIGHPAGE
+void copy_highpage(struct page *to, struct page *from);
+
+/* Unlike sparc32, sparc64's parameter passing API is more
+ * sane in that structures which as small enough are passed
+ * in registers instead of on the stack. Thus, setting
+ * STRICT_MM_TYPECHECKS does not generate worse code so
+ * let's enable it to get the type checking.
+ */
+
+#define STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/* These are used to make use of C type-checking.. */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long iopte; } iopte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pud; } pud_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define iopte_val(x) ((x).iopte)
+#define pmd_val(x) ((x).pmd)
+#define pud_val(x) ((x).pud)
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __iopte(x) ((iopte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { (x) } )
+#define __pud(x) ((pud_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+#else
+/* .. while these make it easier on the compiler */
+typedef unsigned long pte_t;
+typedef unsigned long iopte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pud_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x) (x)
+#define iopte_val(x) (x)
+#define pmd_val(x) (x)
+#define pud_val(x) (x)
+#define pgd_val(x) (x)
+#define pgprot_val(x) (x)
+
+#define __pte(x) (x)
+#define __iopte(x) (x)
+#define __pmd(x) (x)
+#define __pud(x) (x)
+#define __pgd(x) (x)
+#define __pgprot(x) (x)
+
+#endif /* (STRICT_MM_TYPECHECKS) */
+
+typedef pte_t *pgtable_t;
+
+extern unsigned long sparc64_va_hole_top;
+extern unsigned long sparc64_va_hole_bottom;
+
+/* The next two defines specify the actual exclusion region we
+ * enforce, wherein we use a 4GB red zone on each side of the VA hole.
+ */
+#define VA_EXCLUDE_START (sparc64_va_hole_bottom - (1UL << 32UL))
+#define VA_EXCLUDE_END (sparc64_va_hole_top + (1UL << 32UL))
+
+#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
+ _AC(0x0000000070000000,UL) : \
+ VA_EXCLUDE_END)
+
+#include <asm-generic/memory_model.h>
+
+extern unsigned long PAGE_OFFSET;
+
+#endif /* !(__ASSEMBLY__) */
+
+/* The maximum number of physical memory address bits we support. The
+ * largest value we can support is whatever "KPGD_SHIFT + KPTE_BITS"
+ * evaluates to.
+ */
+#define MAX_PHYS_ADDRESS_BITS 53
+
+#define ILOG2_4MB 22
+#define ILOG2_256MB 28
+
+#ifndef __ASSEMBLY__
+
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
+
+#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
+
+#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_phys __pa
+#define phys_to_virt __va
+
+#endif /* !(__ASSEMBLY__) */
+
+#include <asm-generic/getorder.h>
+
+#endif /* _SPARC64_PAGE_H */
diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h
new file mode 100644
index 000000000..0a7ffcfd5
--- /dev/null
+++ b/arch/sparc/include/asm/parport.h
@@ -0,0 +1,256 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* parport.h: sparc64 specific parport initialization and dma.
+ *
+ * Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be)
+ */
+
+#ifndef _ASM_SPARC64_PARPORT_H
+#define _ASM_SPARC64_PARPORT_H 1
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <asm/ebus_dma.h>
+#include <asm/ns87303.h>
+#include <asm/prom.h>
+
+#define PARPORT_PC_MAX_PORTS PARPORT_MAX
+
+/*
+ * While sparc64 doesn't have an ISA DMA API, we provide something that looks
+ * close enough to make parport_pc happy
+ */
+#define HAS_DMA
+
+#ifdef CONFIG_PARPORT_PC_FIFO
+static DEFINE_SPINLOCK(dma_spin_lock);
+
+#define claim_dma_lock() \
+({ unsigned long flags; \
+ spin_lock_irqsave(&dma_spin_lock, flags); \
+ flags; \
+})
+
+#define release_dma_lock(__flags) \
+ spin_unlock_irqrestore(&dma_spin_lock, __flags);
+#endif
+
+static struct sparc_ebus_info {
+ struct ebus_dma_info info;
+ unsigned int addr;
+ unsigned int count;
+ int lock;
+
+ struct parport *port;
+} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
+
+static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
+
+static inline int request_dma(unsigned int dmanr, const char *device_id)
+{
+ if (dmanr >= PARPORT_PC_MAX_PORTS)
+ return -EINVAL;
+ if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
+ return -EBUSY;
+ return 0;
+}
+
+static inline void free_dma(unsigned int dmanr)
+{
+ if (dmanr >= PARPORT_PC_MAX_PORTS) {
+ printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
+ return;
+ }
+ if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
+ printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
+ return;
+ }
+}
+
+static inline void enable_dma(unsigned int dmanr)
+{
+ ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
+
+ if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
+ sparc_ebus_dmas[dmanr].addr,
+ sparc_ebus_dmas[dmanr].count))
+ BUG();
+}
+
+static inline void disable_dma(unsigned int dmanr)
+{
+ ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
+}
+
+static inline void clear_dma_ff(unsigned int dmanr)
+{
+ /* nothing */
+}
+
+static inline void set_dma_mode(unsigned int dmanr, char mode)
+{
+ ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
+}
+
+static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
+{
+ sparc_ebus_dmas[dmanr].addr = addr;
+}
+
+static inline void set_dma_count(unsigned int dmanr, unsigned int count)
+{
+ sparc_ebus_dmas[dmanr].count = count;
+}
+
+static inline unsigned int get_dma_residue(unsigned int dmanr)
+{
+ return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
+}
+
+static int ecpp_probe(struct platform_device *op)
+{
+ unsigned long base = op->resource[0].start;
+ unsigned long config = op->resource[1].start;
+ unsigned long d_base = op->resource[2].start;
+ unsigned long d_len;
+ struct device_node *parent;
+ struct parport *p;
+ int slot, err;
+
+ parent = op->dev.of_node->parent;
+ if (of_node_name_eq(parent, "dma")) {
+ p = parport_pc_probe_port(base, base + 0x400,
+ op->archdata.irqs[0], PARPORT_DMA_NOFIFO,
+ op->dev.parent->parent, 0);
+ if (!p)
+ return -ENOMEM;
+ dev_set_drvdata(&op->dev, p);
+ return 0;
+ }
+
+ for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
+ if (!test_and_set_bit(slot, dma_slot_map))
+ break;
+ }
+ err = -ENODEV;
+ if (slot >= PARPORT_PC_MAX_PORTS)
+ goto out_err;
+
+ spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
+
+ d_len = (op->resource[2].end - d_base) + 1UL;
+ sparc_ebus_dmas[slot].info.regs =
+ of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
+
+ if (!sparc_ebus_dmas[slot].info.regs)
+ goto out_clear_map;
+
+ sparc_ebus_dmas[slot].info.flags = 0;
+ sparc_ebus_dmas[slot].info.callback = NULL;
+ sparc_ebus_dmas[slot].info.client_cookie = NULL;
+ sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
+ strcpy(sparc_ebus_dmas[slot].info.name, "parport");
+ if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
+ goto out_unmap_regs;
+
+ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
+
+ /* Configure IRQ to Push Pull, Level Low */
+ /* Enable ECP, set bit 2 of the CTR first */
+ outb(0x04, base + 0x02);
+ ns87303_modify(config, PCR,
+ PCR_EPP_ENABLE |
+ PCR_IRQ_ODRAIN,
+ PCR_ECP_ENABLE |
+ PCR_ECP_CLK_ENA |
+ PCR_IRQ_POLAR);
+
+ /* CTR bit 5 controls direction of port */
+ ns87303_modify(config, PTR,
+ 0, PTR_LPT_REG_DIR);
+
+ p = parport_pc_probe_port(base, base + 0x400,
+ op->archdata.irqs[0],
+ slot,
+ op->dev.parent,
+ 0);
+ err = -ENOMEM;
+ if (!p)
+ goto out_disable_irq;
+
+ dev_set_drvdata(&op->dev, p);
+
+ return 0;
+
+out_disable_irq:
+ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
+ ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
+
+out_unmap_regs:
+ of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
+
+out_clear_map:
+ clear_bit(slot, dma_slot_map);
+
+out_err:
+ return err;
+}
+
+static int ecpp_remove(struct platform_device *op)
+{
+ struct parport *p = dev_get_drvdata(&op->dev);
+ int slot = p->dma;
+
+ parport_pc_unregister_port(p);
+
+ if (slot != PARPORT_DMA_NOFIFO) {
+ unsigned long d_base = op->resource[2].start;
+ unsigned long d_len;
+
+ d_len = (op->resource[2].end - d_base) + 1UL;
+
+ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
+ ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
+ of_iounmap(&op->resource[2],
+ sparc_ebus_dmas[slot].info.regs,
+ d_len);
+ clear_bit(slot, dma_slot_map);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id ecpp_match[] = {
+ {
+ .name = "ecpp",
+ },
+ {
+ .name = "parallel",
+ .compatible = "ecpp",
+ },
+ {
+ .name = "parallel",
+ .compatible = "ns87317-ecpp",
+ },
+ {
+ .name = "parallel",
+ .compatible = "pnpALI,1533,3",
+ },
+ {},
+};
+
+static struct platform_driver ecpp_driver = {
+ .driver = {
+ .name = "ecpp",
+ .of_match_table = ecpp_match,
+ },
+ .probe = ecpp_probe,
+ .remove = ecpp_remove,
+};
+
+static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
+{
+ return platform_driver_register(&ecpp_driver);
+}
+
+#endif /* !(_ASM_SPARC64_PARPORT_H */
diff --git a/arch/sparc/include/asm/pbm.h b/arch/sparc/include/asm/pbm.h
new file mode 100644
index 000000000..0c8626172
--- /dev/null
+++ b/arch/sparc/include/asm/pbm.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * pbm.h: PCI bus module pseudo driver software state
+ * Adopted from sparc64 by V. Roganov and G. Raiko
+ *
+ * Original header:
+ * pbm.h: U2P PCI bus module pseudo driver software state.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * To put things into perspective, consider sparc64 with a few PCI controllers.
+ * Each type would have an own structure, with instances related one to one.
+ * We have only pcic on sparc, but we want to be compatible with sparc64 pbm.h.
+ * All three represent different abstractions.
+ * pci_bus - Linux PCI subsystem view of a PCI bus (including bridged buses)
+ * pbm - Arch-specific view of a PCI bus (sparc or sparc64)
+ * pcic - Chip-specific information for PCIC.
+ */
+
+#ifndef __SPARC_PBM_H
+#define __SPARC_PBM_H
+
+#include <linux/pci.h>
+#include <asm/oplib.h>
+#include <asm/prom.h>
+
+struct linux_pbm_info {
+ int prom_node;
+ char prom_name[64];
+ /* struct linux_prom_pci_ranges pbm_ranges[PROMREG_MAX]; */
+ /* int num_pbm_ranges; */
+
+ /* Now things for the actual PCI bus probes. */
+ unsigned int pci_first_busno; /* Can it be nonzero? */
+ struct pci_bus *pci_bus; /* Was inline, MJ allocs now */
+};
+
+/* PCI devices which are not bridges have this placed in their pci_dev
+ * sysdata member. This makes OBP aware PCI device drivers easier to
+ * code.
+ */
+struct pcidev_cookie {
+ struct linux_pbm_info *pbm;
+ struct device_node *prom_node;
+};
+
+#endif /* !(__SPARC_PBM_H) */
diff --git a/arch/sparc/include/asm/pci.h b/arch/sparc/include/asm/pci.h
new file mode 100644
index 000000000..1419aa84d
--- /dev/null
+++ b/arch/sparc/include/asm/pci.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_PCI_H
+#define ___ASM_SPARC_PCI_H
+
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes
+ * or architectures with incomplete PCI setup by the loader.
+ */
+#define pcibios_assign_all_busses() 0
+
+#define PCIBIOS_MIN_IO 0UL
+#define PCIBIOS_MIN_MEM 0UL
+
+#define PCI_IRQ_NONE 0xffffffff
+
+
+#ifdef CONFIG_SPARC64
+
+/* PCI IOMMU mapping bypass support. */
+
+/* PCI 64-bit addressing works for all slots on all controller
+ * types on sparc64. However, it requires that the device
+ * can drive enough of the 64 bits.
+ */
+#define PCI64_REQUIRED_MASK (~(u64)0)
+#define PCI64_ADDR_BASE 0xfffc000000000000UL
+
+/* Return the index of the PCI controller for device PDEV. */
+int pci_domain_nr(struct pci_bus *bus);
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+ return 1;
+}
+
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+#define HAVE_PCI_MMAP
+#define arch_can_pci_mmap_io() 1
+#define HAVE_ARCH_PCI_GET_UNMAPPED_AREA
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
+#define get_pci_unmapped_area get_fb_unmapped_area
+#endif /* CONFIG_SPARC64 */
+
+#endif /* ___ASM_SPARC_PCI_H */
diff --git a/arch/sparc/include/asm/pcic.h b/arch/sparc/include/asm/pcic.h
new file mode 100644
index 000000000..238376b1f
--- /dev/null
+++ b/arch/sparc/include/asm/pcic.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * pcic.h: JavaEngine 1 specific PCI definitions.
+ *
+ * Copyright (C) 1998 V. Roganov and G. Raiko
+ */
+
+#ifndef __SPARC_PCIC_H
+#define __SPARC_PCIC_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <linux/smp.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/pbm.h>
+
+struct linux_pcic {
+ void __iomem *pcic_regs;
+ unsigned long pcic_io;
+ void __iomem *pcic_config_space_addr;
+ void __iomem *pcic_config_space_data;
+ struct resource pcic_res_regs;
+ struct resource pcic_res_io;
+ struct resource pcic_res_cfg_addr;
+ struct resource pcic_res_cfg_data;
+ struct linux_pbm_info pbm;
+ struct pcic_ca2irq *pcic_imap;
+ int pcic_imdim;
+};
+
+#ifdef CONFIG_PCIC_PCI
+int pcic_present(void);
+int pcic_probe(void);
+void pci_time_init(void);
+void sun4m_pci_init_IRQ(void);
+#else
+static inline int pcic_present(void) { return 0; }
+static inline int pcic_probe(void) { return 0; }
+static inline void pci_time_init(void) {}
+static inline void sun4m_pci_init_IRQ(void) {}
+#endif
+#endif
+
+/* Size of PCI I/O space which we relocate. */
+#define PCI_SPACE_SIZE 0x1000000 /* 16 MB */
+
+/* PCIC Register Set. */
+#define PCI_DIAGNOSTIC_0 0x40 /* 32 bits */
+#define PCI_SIZE_0 0x44 /* 32 bits */
+#define PCI_SIZE_1 0x48 /* 32 bits */
+#define PCI_SIZE_2 0x4c /* 32 bits */
+#define PCI_SIZE_3 0x50 /* 32 bits */
+#define PCI_SIZE_4 0x54 /* 32 bits */
+#define PCI_SIZE_5 0x58 /* 32 bits */
+#define PCI_PIO_CONTROL 0x60 /* 8 bits */
+#define PCI_DVMA_CONTROL 0x62 /* 8 bits */
+#define PCI_DVMA_CONTROL_INACTIVITY_REQ (1<<0)
+#define PCI_DVMA_CONTROL_IOTLB_ENABLE (1<<0)
+#define PCI_DVMA_CONTROL_IOTLB_DISABLE 0
+#define PCI_DVMA_CONTROL_INACTIVITY_ACK (1<<4)
+#define PCI_INTERRUPT_CONTROL 0x63 /* 8 bits */
+#define PCI_CPU_INTERRUPT_PENDING 0x64 /* 32 bits */
+#define PCI_DIAGNOSTIC_1 0x68 /* 16 bits */
+#define PCI_SOFTWARE_INT_CLEAR 0x6a /* 16 bits */
+#define PCI_SOFTWARE_INT_SET 0x6e /* 16 bits */
+#define PCI_SYS_INT_PENDING 0x70 /* 32 bits */
+#define PCI_SYS_INT_PENDING_PIO 0x40000000
+#define PCI_SYS_INT_PENDING_DMA 0x20000000
+#define PCI_SYS_INT_PENDING_PCI 0x10000000
+#define PCI_SYS_INT_PENDING_APSR 0x08000000
+#define PCI_SYS_INT_TARGET_MASK 0x74 /* 32 bits */
+#define PCI_SYS_INT_TARGET_MASK_CLEAR 0x78 /* 32 bits */
+#define PCI_SYS_INT_TARGET_MASK_SET 0x7c /* 32 bits */
+#define PCI_SYS_INT_PENDING_CLEAR 0x83 /* 8 bits */
+#define PCI_SYS_INT_PENDING_CLEAR_ALL 0x80
+#define PCI_SYS_INT_PENDING_CLEAR_PIO 0x40
+#define PCI_SYS_INT_PENDING_CLEAR_DMA 0x20
+#define PCI_SYS_INT_PENDING_CLEAR_PCI 0x10
+#define PCI_IOTLB_CONTROL 0x84 /* 8 bits */
+#define PCI_INT_SELECT_LO 0x88 /* 16 bits */
+#define PCI_ARBITRATION_SELECT 0x8a /* 16 bits */
+#define PCI_INT_SELECT_HI 0x8c /* 16 bits */
+#define PCI_HW_INT_OUTPUT 0x8e /* 16 bits */
+#define PCI_IOTLB_RAM_INPUT 0x90 /* 32 bits */
+#define PCI_IOTLB_CAM_INPUT 0x94 /* 32 bits */
+#define PCI_IOTLB_RAM_OUTPUT 0x98 /* 32 bits */
+#define PCI_IOTLB_CAM_OUTPUT 0x9c /* 32 bits */
+#define PCI_SMBAR0 0xa0 /* 8 bits */
+#define PCI_MSIZE0 0xa1 /* 8 bits */
+#define PCI_PMBAR0 0xa2 /* 8 bits */
+#define PCI_SMBAR1 0xa4 /* 8 bits */
+#define PCI_MSIZE1 0xa5 /* 8 bits */
+#define PCI_PMBAR1 0xa6 /* 8 bits */
+#define PCI_SIBAR 0xa8 /* 8 bits */
+#define PCI_SIBAR_ADDRESS_MASK 0xf
+#define PCI_ISIZE 0xa9 /* 8 bits */
+#define PCI_ISIZE_16M 0xf
+#define PCI_ISIZE_32M 0xe
+#define PCI_ISIZE_64M 0xc
+#define PCI_ISIZE_128M 0x8
+#define PCI_ISIZE_256M 0x0
+#define PCI_PIBAR 0xaa /* 8 bits */
+#define PCI_CPU_COUNTER_LIMIT_HI 0xac /* 32 bits */
+#define PCI_CPU_COUNTER_LIMIT_LO 0xb0 /* 32 bits */
+#define PCI_CPU_COUNTER_LIMIT 0xb4 /* 32 bits */
+#define PCI_SYS_LIMIT 0xb8 /* 32 bits */
+#define PCI_SYS_COUNTER 0xbc /* 32 bits */
+#define PCI_SYS_COUNTER_OVERFLOW (1<<31) /* Limit reached */
+#define PCI_SYS_LIMIT_PSEUDO 0xc0 /* 32 bits */
+#define PCI_USER_TIMER_CONTROL 0xc4 /* 8 bits */
+#define PCI_USER_TIMER_CONFIG 0xc5 /* 8 bits */
+#define PCI_COUNTER_IRQ 0xc6 /* 8 bits */
+#define PCI_COUNTER_IRQ_SET(sys_irq, cpu_irq) ((((sys_irq) & 0xf) << 4) | \
+ ((cpu_irq) & 0xf))
+#define PCI_COUNTER_IRQ_SYS(v) (((v) >> 4) & 0xf)
+#define PCI_COUNTER_IRQ_CPU(v) ((v) & 0xf)
+#define PCI_PIO_ERROR_COMMAND 0xc7 /* 8 bits */
+#define PCI_PIO_ERROR_ADDRESS 0xc8 /* 32 bits */
+#define PCI_IOTLB_ERROR_ADDRESS 0xcc /* 32 bits */
+#define PCI_SYS_STATUS 0xd0 /* 8 bits */
+#define PCI_SYS_STATUS_RESET_ENABLE (1<<0)
+#define PCI_SYS_STATUS_RESET (1<<1)
+#define PCI_SYS_STATUS_WATCHDOG_RESET (1<<4)
+#define PCI_SYS_STATUS_PCI_RESET (1<<5)
+#define PCI_SYS_STATUS_PCI_RESET_ENABLE (1<<6)
+#define PCI_SYS_STATUS_PCI_SATTELITE_MODE (1<<7)
+
+#endif /* !(__SPARC_PCIC_H) */
diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h
new file mode 100644
index 000000000..da834ffbe
--- /dev/null
+++ b/arch/sparc/include/asm/pcr.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PCR_H
+#define __PCR_H
+
+struct pcr_ops {
+ u64 (*read_pcr)(unsigned long);
+ void (*write_pcr)(unsigned long, u64);
+ u64 (*read_pic)(unsigned long);
+ void (*write_pic)(unsigned long, u64);
+ u64 (*nmi_picl_value)(unsigned int nmi_hz);
+ u64 pcr_nmi_enable;
+ u64 pcr_nmi_disable;
+};
+extern const struct pcr_ops *pcr_ops;
+
+void deferred_pcr_work_irq(int irq, struct pt_regs *regs);
+void schedule_deferred_pcr_work(void);
+
+#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */
+#define PCR_STRACE 0x00000002 /* Trace supervisor events */
+#define PCR_UTRACE 0x00000004 /* Trace user events */
+#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */
+#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */
+#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */
+#define PCR_N2_MASK0 0x00003fc0
+#define PCR_N2_MASK0_SHIFT 6
+#define PCR_N2_SL0 0x0003c000
+#define PCR_N2_SL0_SHIFT 14
+#define PCR_N2_OV0 0x00040000
+#define PCR_N2_MASK1 0x07f80000
+#define PCR_N2_MASK1_SHIFT 19
+#define PCR_N2_SL1 0x78000000
+#define PCR_N2_SL1_SHIFT 27
+#define PCR_N2_OV1 0x80000000
+
+#define PCR_N4_OV 0x00000001 /* PIC overflow */
+#define PCR_N4_TOE 0x00000002 /* Trap On Event */
+#define PCR_N4_UTRACE 0x00000004 /* Trace user events */
+#define PCR_N4_STRACE 0x00000008 /* Trace supervisor events */
+#define PCR_N4_HTRACE 0x00000010 /* Trace hypervisor events */
+#define PCR_N4_MASK 0x000007e0 /* Event mask */
+#define PCR_N4_MASK_SHIFT 5
+#define PCR_N4_SL 0x0000f800 /* Event Select */
+#define PCR_N4_SL_SHIFT 11
+#define PCR_N4_PICNPT 0x00010000 /* PIC non-privileged trap */
+#define PCR_N4_PICNHT 0x00020000 /* PIC non-hypervisor trap */
+#define PCR_N4_NTC 0x00040000 /* Next-To-Commit wrap */
+
+int pcr_arch_init(void);
+
+#endif /* __PCR_H */
diff --git a/arch/sparc/include/asm/percpu.h b/arch/sparc/include/asm/percpu.h
new file mode 100644
index 000000000..0cd704ef5
--- /dev/null
+++ b/arch/sparc/include/asm/percpu.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_PERCPU_H
+#define ___ASM_SPARC_PERCPU_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/percpu_64.h>
+#else
+#include <asm/percpu_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/percpu_32.h b/arch/sparc/include/asm/percpu_32.h
new file mode 100644
index 000000000..ee6c7c193
--- /dev/null
+++ b/arch/sparc/include/asm/percpu_32.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ARCH_SPARC_PERCPU__
+#define __ARCH_SPARC_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_SPARC_PERCPU__ */
diff --git a/arch/sparc/include/asm/percpu_64.h b/arch/sparc/include/asm/percpu_64.h
new file mode 100644
index 000000000..a8786a4b9
--- /dev/null
+++ b/arch/sparc/include/asm/percpu_64.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ARCH_SPARC64_PERCPU__
+#define __ARCH_SPARC64_PERCPU__
+
+#include <linux/compiler.h>
+
+#ifndef BUILD_VDSO
+register unsigned long __local_per_cpu_offset asm("g5");
+#endif
+
+#ifdef CONFIG_SMP
+
+#include <asm/trap_block.h>
+
+#define __per_cpu_offset(__cpu) \
+ (trap_block[(__cpu)].__per_cpu_base)
+#define per_cpu_offset(x) (__per_cpu_offset(x))
+
+#define __my_cpu_offset __local_per_cpu_offset
+
+#else /* ! SMP */
+
+#endif /* SMP */
+
+#include <asm-generic/percpu.h>
+
+#endif /* __ARCH_SPARC64_PERCPU__ */
diff --git a/arch/sparc/include/asm/perf_event.h b/arch/sparc/include/asm/perf_event.h
new file mode 100644
index 000000000..c2aec0c7f
--- /dev/null
+++ b/arch/sparc/include/asm/perf_event.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_SPARC_PERF_EVENT_H
+#define __ASM_SPARC_PERF_EVENT_H
+
+#ifdef CONFIG_PERF_EVENTS
+#include <asm/ptrace.h>
+
+#define perf_arch_fetch_caller_regs(regs, ip) \
+do { \
+ unsigned long _pstate, _asi, _pil, _i7, _fp; \
+ __asm__ __volatile__("rdpr %%pstate, %0\n\t" \
+ "rd %%asi, %1\n\t" \
+ "rdpr %%pil, %2\n\t" \
+ "mov %%i7, %3\n\t" \
+ "mov %%i6, %4\n\t" \
+ : "=r" (_pstate), \
+ "=r" (_asi), \
+ "=r" (_pil), \
+ "=r" (_i7), \
+ "=r" (_fp)); \
+ (regs)->tstate = (_pstate << 8) | \
+ (_asi << 24) | (_pil << 20); \
+ (regs)->tpc = (ip); \
+ (regs)->tnpc = (regs)->tpc + 4; \
+ (regs)->u_regs[UREG_I6] = _fp; \
+ (regs)->u_regs[UREG_I7] = _i7; \
+} while (0)
+#endif
+
+#endif
diff --git a/arch/sparc/include/asm/pgalloc.h b/arch/sparc/include/asm/pgalloc.h
new file mode 100644
index 000000000..9ea0b3758
--- /dev/null
+++ b/arch/sparc/include/asm/pgalloc.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_PGALLOC_H
+#define ___ASM_SPARC_PGALLOC_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/pgalloc_64.h>
+#else
+#include <asm/pgalloc_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/pgalloc_32.h b/arch/sparc/include/asm/pgalloc_32.h
new file mode 100644
index 000000000..4f73e87b2
--- /dev/null
+++ b/arch/sparc/include/asm/pgalloc_32.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_PGALLOC_H
+#define _SPARC_PGALLOC_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/pgtable.h>
+
+#include <asm/pgtsrmmu.h>
+#include <asm/vaddrs.h>
+#include <asm/page.h>
+
+struct page;
+
+void *srmmu_get_nocache(int size, int align);
+void srmmu_free_nocache(void *addr, int size);
+
+extern struct resource sparc_iomap;
+
+pgd_t *get_pgd_fast(void);
+static inline void free_pgd_fast(pgd_t *pgd)
+{
+ srmmu_free_nocache(pgd, SRMMU_PGD_TABLE_SIZE);
+}
+
+#define pgd_free(mm, pgd) free_pgd_fast(pgd)
+#define pgd_alloc(mm) get_pgd_fast()
+
+static inline void pud_set(pud_t * pudp, pmd_t * pmdp)
+{
+ unsigned long pa = __nocache_pa(pmdp);
+
+ set_pte((pte_t *)pudp, __pte((SRMMU_ET_PTD | (pa >> 4))));
+}
+
+#define pud_populate(MM, PGD, PMD) pud_set(PGD, PMD)
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm,
+ unsigned long address)
+{
+ return srmmu_get_nocache(SRMMU_PMD_TABLE_SIZE,
+ SRMMU_PMD_TABLE_SIZE);
+}
+
+static inline void free_pmd_fast(pmd_t * pmd)
+{
+ srmmu_free_nocache(pmd, SRMMU_PMD_TABLE_SIZE);
+}
+
+#define pmd_free(mm, pmd) free_pmd_fast(pmd)
+#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tlb)->mm, pmd)
+
+#define pmd_populate(mm, pmd, pte) pmd_set(pmd, pte)
+
+void pmd_set(pmd_t *pmdp, pte_t *ptep);
+#define pmd_populate_kernel pmd_populate
+
+pgtable_t pte_alloc_one(struct mm_struct *mm);
+
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
+{
+ return srmmu_get_nocache(SRMMU_PTE_TABLE_SIZE,
+ SRMMU_PTE_TABLE_SIZE);
+}
+
+
+static inline void free_pte_fast(pte_t *pte)
+{
+ srmmu_free_nocache(pte, SRMMU_PTE_TABLE_SIZE);
+}
+
+#define pte_free_kernel(mm, pte) free_pte_fast(pte)
+
+void pte_free(struct mm_struct * mm, pgtable_t pte);
+#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
+
+#endif /* _SPARC_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgalloc_64.h b/arch/sparc/include/asm/pgalloc_64.h
new file mode 100644
index 000000000..caa7632be
--- /dev/null
+++ b/arch/sparc/include/asm/pgalloc_64.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_PGALLOC_H
+#define _SPARC64_PGALLOC_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <asm/spitfire.h>
+#include <asm/cpudata.h>
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+
+/* Page table allocation/freeing. */
+
+extern struct kmem_cache *pgtable_cache;
+
+static inline void __p4d_populate(p4d_t *p4d, pud_t *pud)
+{
+ p4d_set(p4d, pud);
+}
+
+#define p4d_populate(MM, P4D, PUD) __p4d_populate(P4D, PUD)
+
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+ return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+ kmem_cache_free(pgtable_cache, pgd);
+}
+
+static inline void __pud_populate(pud_t *pud, pmd_t *pmd)
+{
+ pud_set(pud, pmd);
+}
+
+#define pud_populate(MM, PUD, PMD) __pud_populate(PUD, PMD)
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+ return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+ kmem_cache_free(pgtable_cache, pud);
+}
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+ return kmem_cache_alloc(pgtable_cache, GFP_KERNEL);
+}
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+ kmem_cache_free(pgtable_cache, pmd);
+}
+
+pte_t *pte_alloc_one_kernel(struct mm_struct *mm);
+pgtable_t pte_alloc_one(struct mm_struct *mm);
+void pte_free_kernel(struct mm_struct *mm, pte_t *pte);
+void pte_free(struct mm_struct *mm, pgtable_t ptepage);
+
+/* arch use pte_free_defer() implementation in arch/sparc/mm/init_64.c */
+#define pte_free_defer pte_free_defer
+void pte_free_defer(struct mm_struct *mm, pgtable_t pgtable);
+
+#define pmd_populate_kernel(MM, PMD, PTE) pmd_set(MM, PMD, PTE)
+#define pmd_populate(MM, PMD, PTE) pmd_set(MM, PMD, PTE)
+
+void pgtable_free(void *table, bool is_page);
+
+#ifdef CONFIG_SMP
+
+struct mmu_gather;
+void tlb_remove_table(struct mmu_gather *, void *);
+
+static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
+{
+ unsigned long pgf = (unsigned long)table;
+ if (is_page)
+ pgf |= 0x1UL;
+ tlb_remove_table(tlb, (void *)pgf);
+}
+
+static inline void __tlb_remove_table(void *_table)
+{
+ void *table = (void *)((unsigned long)_table & ~0x1UL);
+ bool is_page = false;
+
+ if ((unsigned long)_table & 0x1UL)
+ is_page = true;
+ pgtable_free(table, is_page);
+}
+#else /* CONFIG_SMP */
+static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, bool is_page)
+{
+ pgtable_free(table, is_page);
+}
+#endif /* !CONFIG_SMP */
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pte_t *pte,
+ unsigned long address)
+{
+ pgtable_free_tlb(tlb, pte, true);
+}
+
+#define __pmd_free_tlb(tlb, pmd, addr) \
+ pgtable_free_tlb(tlb, pmd, false)
+
+#define __pud_free_tlb(tlb, pud, addr) \
+ pgtable_free_tlb(tlb, pud, false)
+
+#endif /* _SPARC64_PGALLOC_H */
diff --git a/arch/sparc/include/asm/pgtable.h b/arch/sparc/include/asm/pgtable.h
new file mode 100644
index 000000000..e48891170
--- /dev/null
+++ b/arch/sparc/include/asm/pgtable.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_PGTABLE_H
+#define ___ASM_SPARC_PGTABLE_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/pgtable_64.h>
+#else
+#include <asm/pgtable_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
new file mode 100644
index 000000000..9e85d57ac
--- /dev/null
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -0,0 +1,441 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_PGTABLE_H
+#define _SPARC_PGTABLE_H
+
+/* asm/pgtable.h: Defines and functions used to work
+ * with Sparc page tables.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/const.h>
+
+#define PMD_SHIFT 18
+#define PMD_SIZE (1UL << PMD_SHIFT)
+#define PMD_MASK (~(PMD_SIZE-1))
+#define PMD_ALIGN(__addr) (((__addr) + ~PMD_MASK) & PMD_MASK)
+
+#define PGDIR_SHIFT 24
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+#define PGDIR_ALIGN(__addr) (((__addr) + ~PGDIR_MASK) & PGDIR_MASK)
+
+#ifndef __ASSEMBLY__
+#include <asm-generic/pgtable-nopud.h>
+
+#include <linux/spinlock.h>
+#include <linux/mm_types.h>
+#include <asm/types.h>
+#include <asm/pgtsrmmu.h>
+#include <asm/vaddrs.h>
+#include <asm/oplib.h>
+#include <asm/cpu_type.h>
+
+
+struct vm_area_struct;
+struct page;
+
+void load_mmu(void);
+unsigned long calc_highpages(void);
+unsigned long __init bootmem_init(unsigned long *pages_avail);
+
+#define pte_ERROR(e) __builtin_trap()
+#define pmd_ERROR(e) __builtin_trap()
+#define pgd_ERROR(e) __builtin_trap()
+
+#define PTRS_PER_PTE 64
+#define PTRS_PER_PMD 64
+#define PTRS_PER_PGD 256
+#define USER_PTRS_PER_PGD PAGE_OFFSET / PGDIR_SIZE
+#define PTE_SIZE (PTRS_PER_PTE*4)
+
+#define PAGE_NONE SRMMU_PAGE_NONE
+#define PAGE_SHARED SRMMU_PAGE_SHARED
+#define PAGE_COPY SRMMU_PAGE_COPY
+#define PAGE_READONLY SRMMU_PAGE_RDONLY
+#define PAGE_KERNEL SRMMU_PAGE_KERNEL
+
+/* Top-level page directory - dummy used by init-mm.
+ * srmmu.c will assign the real one (which is dynamically sized) */
+#define swapper_pg_dir NULL
+
+void paging_init(void);
+
+extern unsigned long ptr_in_current_pgd;
+
+/* First physical page can be anywhere, the following is needed so that
+ * va-->pa and vice versa conversions work properly without performance
+ * hit for all __pa()/__va() operations.
+ */
+extern unsigned long phys_base;
+extern unsigned long pfn_base;
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+/*
+ * In general all page table modifications should use the V8 atomic
+ * swap instruction. This insures the mmu and the cpu are in sync
+ * with respect to ref/mod bits in the page tables.
+ */
+static inline unsigned long srmmu_swap(unsigned long *addr, unsigned long value)
+{
+ __asm__ __volatile__("swap [%2], %0" :
+ "=&r" (value) : "0" (value), "r" (addr) : "memory");
+ return value;
+}
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified. Thus, the following
+ * hook is made available.
+ */
+
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+ srmmu_swap((unsigned long *)ptep, pte_val(pteval));
+}
+
+static inline int srmmu_device_memory(unsigned long x)
+{
+ return ((x & 0xF0000000) != 0);
+}
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+ return (pmd_val(pmd) & SRMMU_PTD_PMASK) >> (PAGE_SHIFT-4);
+}
+
+static inline struct page *pmd_page(pmd_t pmd)
+{
+ if (srmmu_device_memory(pmd_val(pmd)))
+ BUG();
+ return pfn_to_page(pmd_pfn(pmd));
+}
+
+static inline unsigned long __pmd_page(pmd_t pmd)
+{
+ unsigned long v;
+
+ if (srmmu_device_memory(pmd_val(pmd)))
+ BUG();
+
+ v = pmd_val(pmd) & SRMMU_PTD_PMASK;
+ return (unsigned long)__nocache_va(v << 4);
+}
+
+static inline unsigned long pmd_page_vaddr(pmd_t pmd)
+{
+ unsigned long v = pmd_val(pmd) & SRMMU_PTD_PMASK;
+ return (unsigned long)__nocache_va(v << 4);
+}
+
+static inline pmd_t *pud_pgtable(pud_t pud)
+{
+ if (srmmu_device_memory(pud_val(pud))) {
+ return (pmd_t *)~0;
+ } else {
+ unsigned long v = pud_val(pud) & SRMMU_PTD_PMASK;
+ return (pmd_t *)__nocache_va(v << 4);
+ }
+}
+
+static inline int pte_present(pte_t pte)
+{
+ return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE);
+}
+
+static inline int pte_none(pte_t pte)
+{
+ return !pte_val(pte);
+}
+
+static inline void __pte_clear(pte_t *ptep)
+{
+ set_pte(ptep, __pte(0));
+}
+
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ __pte_clear(ptep);
+}
+
+static inline int pmd_bad(pmd_t pmd)
+{
+ return (pmd_val(pmd) & SRMMU_ET_MASK) != SRMMU_ET_PTD;
+}
+
+static inline int pmd_present(pmd_t pmd)
+{
+ return ((pmd_val(pmd) & SRMMU_ET_MASK) == SRMMU_ET_PTD);
+}
+
+static inline int pmd_none(pmd_t pmd)
+{
+ return !pmd_val(pmd);
+}
+
+static inline void pmd_clear(pmd_t *pmdp)
+{
+ set_pte((pte_t *)&pmd_val(*pmdp), __pte(0));
+}
+
+static inline int pud_none(pud_t pud)
+{
+ return !(pud_val(pud) & 0xFFFFFFF);
+}
+
+static inline int pud_bad(pud_t pud)
+{
+ return (pud_val(pud) & SRMMU_ET_MASK) != SRMMU_ET_PTD;
+}
+
+static inline int pud_present(pud_t pud)
+{
+ return ((pud_val(pud) & SRMMU_ET_MASK) == SRMMU_ET_PTD);
+}
+
+static inline void pud_clear(pud_t *pudp)
+{
+ set_pte((pte_t *)pudp, __pte(0));
+}
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+static inline int pte_write(pte_t pte)
+{
+ return pte_val(pte) & SRMMU_WRITE;
+}
+
+static inline int pte_dirty(pte_t pte)
+{
+ return pte_val(pte) & SRMMU_DIRTY;
+}
+
+static inline int pte_young(pte_t pte)
+{
+ return pte_val(pte) & SRMMU_REF;
+}
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+ return __pte(pte_val(pte) & ~SRMMU_WRITE);
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+ return __pte(pte_val(pte) & ~SRMMU_DIRTY);
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+ return __pte(pte_val(pte) & ~SRMMU_REF);
+}
+
+static inline pte_t pte_mkwrite_novma(pte_t pte)
+{
+ return __pte(pte_val(pte) | SRMMU_WRITE);
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+ return __pte(pte_val(pte) | SRMMU_DIRTY);
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+ return __pte(pte_val(pte) | SRMMU_REF);
+}
+
+#define PFN_PTE_SHIFT (PAGE_SHIFT - 4)
+#define pfn_pte(pfn, prot) mk_pte(pfn_to_page(pfn), prot)
+
+static inline unsigned long pte_pfn(pte_t pte)
+{
+ if (srmmu_device_memory(pte_val(pte))) {
+ /* Just return something that will cause
+ * pfn_valid() to return false. This makes
+ * copy_one_pte() to just directly copy to
+ * PTE over.
+ */
+ return ~0UL;
+ }
+ return (pte_val(pte) & SRMMU_PTE_PMASK) >> PFN_PTE_SHIFT;
+}
+
+#define pte_page(pte) pfn_to_page(pte_pfn(pte))
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)
+{
+ return __pte((page_to_pfn(page) << (PAGE_SHIFT-4)) | pgprot_val(pgprot));
+}
+
+static inline pte_t mk_pte_phys(unsigned long page, pgprot_t pgprot)
+{
+ return __pte(((page) >> 4) | pgprot_val(pgprot));
+}
+
+static inline pte_t mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
+{
+ return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot));
+}
+
+#define pgprot_noncached pgprot_noncached
+static inline pgprot_t pgprot_noncached(pgprot_t prot)
+{
+ pgprot_val(prot) &= ~pgprot_val(__pgprot(SRMMU_CACHE));
+ return prot;
+}
+
+static pte_t pte_modify(pte_t pte, pgprot_t newprot) __attribute_const__;
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+ return __pte((pte_val(pte) & SRMMU_CHG_MASK) |
+ pgprot_val(newprot));
+}
+
+/* only used by the huge vmap code, should never be called */
+#define pud_page(pud) NULL
+
+struct seq_file;
+void mmu_info(struct seq_file *m);
+
+/* Fault handler stuff... */
+#define FAULT_CODE_PROT 0x1
+#define FAULT_CODE_WRITE 0x2
+#define FAULT_CODE_USER 0x4
+
+#define update_mmu_cache(vma, address, ptep) do { } while (0)
+#define update_mmu_cache_range(vmf, vma, address, ptep, nr) do { } while (0)
+
+void srmmu_mapiorange(unsigned int bus, unsigned long xpa,
+ unsigned long xva, unsigned int len);
+void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len);
+
+/*
+ * Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
+ * are !pte_none() && !pte_present().
+ *
+ * Format of swap PTEs:
+ *
+ * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * <-------------- offset ---------------> < type -> E 0 0 0 0 0 0
+ */
+static inline unsigned long __swp_type(swp_entry_t entry)
+{
+ return (entry.val >> SRMMU_SWP_TYPE_SHIFT) & SRMMU_SWP_TYPE_MASK;
+}
+
+static inline unsigned long __swp_offset(swp_entry_t entry)
+{
+ return (entry.val >> SRMMU_SWP_OFF_SHIFT) & SRMMU_SWP_OFF_MASK;
+}
+
+static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
+{
+ return (swp_entry_t) {
+ (type & SRMMU_SWP_TYPE_MASK) << SRMMU_SWP_TYPE_SHIFT
+ | (offset & SRMMU_SWP_OFF_MASK) << SRMMU_SWP_OFF_SHIFT };
+}
+
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+static inline int pte_swp_exclusive(pte_t pte)
+{
+ return pte_val(pte) & SRMMU_SWP_EXCLUSIVE;
+}
+
+static inline pte_t pte_swp_mkexclusive(pte_t pte)
+{
+ return __pte(pte_val(pte) | SRMMU_SWP_EXCLUSIVE);
+}
+
+static inline pte_t pte_swp_clear_exclusive(pte_t pte)
+{
+ return __pte(pte_val(pte) & ~SRMMU_SWP_EXCLUSIVE);
+}
+
+static inline unsigned long
+__get_phys (unsigned long addr)
+{
+ switch (sparc_cpu_model){
+ case sun4m:
+ case sun4d:
+ return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
+ default:
+ return 0;
+ }
+}
+
+static inline int
+__get_iospace (unsigned long addr)
+{
+ switch (sparc_cpu_model){
+ case sun4m:
+ case sun4d:
+ return (srmmu_get_pte (addr) >> 28);
+ default:
+ return -1;
+ }
+}
+
+/*
+ * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+ * its high 4 bits. These macros/functions put it there or get it from there.
+ */
+#define MK_IOSPACE_PFN(space, pfn) (pfn | (space << (BITS_PER_LONG - 4)))
+#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
+#define GET_PFN(pfn) (pfn & 0x0fffffffUL)
+
+int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+ unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+ unsigned long from, unsigned long pfn,
+ unsigned long size, pgprot_t prot)
+{
+ unsigned long long offset, space, phys_base;
+
+ offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
+ space = GET_IOSPACE(pfn);
+ phys_base = offset | (space << 32ULL);
+
+ return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+#define io_remap_pfn_range io_remap_pfn_range
+
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+({ \
+ int __changed = !pte_same(*(__ptep), __entry); \
+ if (__changed) { \
+ set_pte(__ptep, __entry); \
+ flush_tlb_page(__vma, __address); \
+ } \
+ __changed; \
+})
+
+#endif /* !(__ASSEMBLY__) */
+
+#define VMALLOC_START _AC(0xfe600000,UL)
+#define VMALLOC_END _AC(0xffc00000,UL)
+
+/* We provide our own get_unmapped_area to cope with VA holes for userland */
+#define HAVE_ARCH_UNMAPPED_AREA
+
+#define pmd_pgtable(pmd) ((pgtable_t)__pmd_page(pmd))
+
+#endif /* !(_SPARC_PGTABLE_H) */
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
new file mode 100644
index 000000000..5e41033bf
--- /dev/null
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -0,0 +1,1181 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * pgtable.h: SpitFire page table operations.
+ *
+ * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef _SPARC64_PGTABLE_H
+#define _SPARC64_PGTABLE_H
+
+/* This file contains the functions and defines necessary to modify and use
+ * the SpitFire page tables.
+ */
+
+#include <asm-generic/pgtable-nop4d.h>
+#include <linux/compiler.h>
+#include <linux/const.h>
+#include <asm/types.h>
+#include <asm/spitfire.h>
+#include <asm/asi.h>
+#include <asm/adi.h>
+#include <asm/page.h>
+#include <asm/processor.h>
+
+/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB).
+ * The page copy blockops can use 0x6000000 to 0x8000000.
+ * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range.
+ * The 4M TSB is mapped in the 0x8400000 to 0x8800000 range.
+ * The PROM resides in an area spanning 0xf0000000 to 0x100000000.
+ * The vmalloc area spans 0x100000000 to 0x200000000.
+ * Since modules need to be in the lowest 32-bits of the address space,
+ * we place them right before the OBP area from 0x10000000 to 0xf0000000.
+ * There is a single static kernel PMD which maps from 0x0 to address
+ * 0x400000000.
+ */
+#define TLBTEMP_BASE _AC(0x0000000006000000,UL)
+#define TSBMAP_8K_BASE _AC(0x0000000008000000,UL)
+#define TSBMAP_4M_BASE _AC(0x0000000008400000,UL)
+#define MODULES_VADDR _AC(0x0000000010000000,UL)
+#define MODULES_LEN _AC(0x00000000e0000000,UL)
+#define MODULES_END _AC(0x00000000f0000000,UL)
+#define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL)
+#define HI_OBP_ADDRESS _AC(0x0000000100000000,UL)
+#define VMALLOC_START _AC(0x0000000100000000,UL)
+#define VMEMMAP_BASE VMALLOC_END
+
+/* PMD_SHIFT determines the size of the area a second-level page
+ * table can map
+ */
+#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3))
+#define PMD_SIZE (_AC(1,UL) << PMD_SHIFT)
+#define PMD_MASK (~(PMD_SIZE-1))
+#define PMD_BITS (PAGE_SHIFT - 3)
+
+/* PUD_SHIFT determines the size of the area a third-level page
+ * table can map
+ */
+#define PUD_SHIFT (PMD_SHIFT + PMD_BITS)
+#define PUD_SIZE (_AC(1,UL) << PUD_SHIFT)
+#define PUD_MASK (~(PUD_SIZE-1))
+#define PUD_BITS (PAGE_SHIFT - 3)
+
+/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
+#define PGDIR_SHIFT (PUD_SHIFT + PUD_BITS)
+#define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+#define PGDIR_BITS (PAGE_SHIFT - 3)
+
+#if (MAX_PHYS_ADDRESS_BITS > PGDIR_SHIFT + PGDIR_BITS)
+#error MAX_PHYS_ADDRESS_BITS exceeds what kernel page tables can support
+#endif
+
+#if (PGDIR_SHIFT + PGDIR_BITS) != 53
+#error Page table parameters do not cover virtual address space properly.
+#endif
+
+#if (PMD_SHIFT != HPAGE_SHIFT)
+#error PMD_SHIFT must equal HPAGE_SHIFT for transparent huge pages.
+#endif
+
+#ifndef __ASSEMBLY__
+
+extern unsigned long VMALLOC_END;
+
+#define vmemmap ((struct page *)VMEMMAP_BASE)
+
+#include <linux/sched.h>
+#include <asm/tlbflush.h>
+
+bool kern_addr_valid(unsigned long addr);
+
+/* Entries per page directory level. */
+#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3))
+#define PTRS_PER_PMD (1UL << PMD_BITS)
+#define PTRS_PER_PUD (1UL << PUD_BITS)
+#define PTRS_PER_PGD (1UL << PGDIR_BITS)
+
+#define pmd_ERROR(e) \
+ pr_err("%s:%d: bad pmd %p(%016lx) seen at (%pS)\n", \
+ __FILE__, __LINE__, &(e), pmd_val(e), __builtin_return_address(0))
+#define pud_ERROR(e) \
+ pr_err("%s:%d: bad pud %p(%016lx) seen at (%pS)\n", \
+ __FILE__, __LINE__, &(e), pud_val(e), __builtin_return_address(0))
+#define pgd_ERROR(e) \
+ pr_err("%s:%d: bad pgd %p(%016lx) seen at (%pS)\n", \
+ __FILE__, __LINE__, &(e), pgd_val(e), __builtin_return_address(0))
+
+#endif /* !(__ASSEMBLY__) */
+
+/* PTE bits which are the same in SUN4U and SUN4V format. */
+#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */
+#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/
+#define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */
+#define _PAGE_PMD_HUGE _AC(0x0100000000000000,UL) /* Huge page */
+#define _PAGE_PUD_HUGE _PAGE_PMD_HUGE
+
+/* SUN4U pte bits... */
+#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */
+#define _PAGE_SZ512K_4U _AC(0x4000000000000000,UL) /* 512K Page */
+#define _PAGE_SZ64K_4U _AC(0x2000000000000000,UL) /* 64K Page */
+#define _PAGE_SZ8K_4U _AC(0x0000000000000000,UL) /* 8K Page */
+#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */
+#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */
+#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */
+#define _PAGE_SPECIAL_4U _AC(0x0200000000000000,UL) /* Special page */
+#define _PAGE_PMD_HUGE_4U _AC(0x0100000000000000,UL) /* Huge page */
+#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */
+#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */
+#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */
+#define _PAGE_SZALL_4U _AC(0x6001000000000000,UL) /* All pgsz bits */
+#define _PAGE_SN_4U _AC(0x0000800000000000,UL) /* (Cheetah) Snoop */
+#define _PAGE_RES2_4U _AC(0x0000780000000000,UL) /* Reserved */
+#define _PAGE_PADDR_4U _AC(0x000007FFFFFFE000,UL) /* (Cheetah) pa[42:13] */
+#define _PAGE_SOFT_4U _AC(0x0000000000001F80,UL) /* Software bits: */
+#define _PAGE_EXEC_4U _AC(0x0000000000001000,UL) /* Executable SW bit */
+#define _PAGE_MODIFIED_4U _AC(0x0000000000000800,UL) /* Modified (dirty) */
+#define _PAGE_ACCESSED_4U _AC(0x0000000000000400,UL) /* Accessed (ref'd) */
+#define _PAGE_READ_4U _AC(0x0000000000000200,UL) /* Readable SW Bit */
+#define _PAGE_WRITE_4U _AC(0x0000000000000100,UL) /* Writable SW Bit */
+#define _PAGE_PRESENT_4U _AC(0x0000000000000080,UL) /* Present */
+#define _PAGE_L_4U _AC(0x0000000000000040,UL) /* Locked TTE */
+#define _PAGE_CP_4U _AC(0x0000000000000020,UL) /* Cacheable in P-Cache */
+#define _PAGE_CV_4U _AC(0x0000000000000010,UL) /* Cacheable in V-Cache */
+#define _PAGE_E_4U _AC(0x0000000000000008,UL) /* side-Effect */
+#define _PAGE_P_4U _AC(0x0000000000000004,UL) /* Privileged Page */
+#define _PAGE_W_4U _AC(0x0000000000000002,UL) /* Writable */
+
+/* SUN4V pte bits... */
+#define _PAGE_NFO_4V _AC(0x4000000000000000,UL) /* No Fault Only */
+#define _PAGE_SOFT2_4V _AC(0x3F00000000000000,UL) /* Software bits, set 2 */
+#define _PAGE_MODIFIED_4V _AC(0x2000000000000000,UL) /* Modified (dirty) */
+#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */
+#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */
+#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */
+#define _PAGE_SPECIAL_4V _AC(0x0200000000000000,UL) /* Special page */
+#define _PAGE_PMD_HUGE_4V _AC(0x0100000000000000,UL) /* Huge page */
+#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */
+#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */
+#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */
+#define _PAGE_CP_4V _AC(0x0000000000000400,UL) /* Cacheable in P-Cache */
+#define _PAGE_CV_4V _AC(0x0000000000000200,UL) /* Cacheable in V-Cache */
+/* Bit 9 is used to enable MCD corruption detection instead on M7 */
+#define _PAGE_MCD_4V _AC(0x0000000000000200,UL) /* Memory Corruption */
+#define _PAGE_P_4V _AC(0x0000000000000100,UL) /* Privileged Page */
+#define _PAGE_EXEC_4V _AC(0x0000000000000080,UL) /* Executable Page */
+#define _PAGE_W_4V _AC(0x0000000000000040,UL) /* Writable */
+#define _PAGE_SOFT_4V _AC(0x0000000000000030,UL) /* Software bits */
+#define _PAGE_PRESENT_4V _AC(0x0000000000000010,UL) /* Present */
+#define _PAGE_RESV_4V _AC(0x0000000000000008,UL) /* Reserved */
+#define _PAGE_SZ16GB_4V _AC(0x0000000000000007,UL) /* 16GB Page */
+#define _PAGE_SZ2GB_4V _AC(0x0000000000000006,UL) /* 2GB Page */
+#define _PAGE_SZ256MB_4V _AC(0x0000000000000005,UL) /* 256MB Page */
+#define _PAGE_SZ32MB_4V _AC(0x0000000000000004,UL) /* 32MB Page */
+#define _PAGE_SZ4MB_4V _AC(0x0000000000000003,UL) /* 4MB Page */
+#define _PAGE_SZ512K_4V _AC(0x0000000000000002,UL) /* 512K Page */
+#define _PAGE_SZ64K_4V _AC(0x0000000000000001,UL) /* 64K Page */
+#define _PAGE_SZ8K_4V _AC(0x0000000000000000,UL) /* 8K Page */
+#define _PAGE_SZALL_4V _AC(0x0000000000000007,UL) /* All pgsz bits */
+
+#define _PAGE_SZBITS_4U _PAGE_SZ8K_4U
+#define _PAGE_SZBITS_4V _PAGE_SZ8K_4V
+
+#if REAL_HPAGE_SHIFT != 22
+#error REAL_HPAGE_SHIFT and _PAGE_SZHUGE_foo must match up
+#endif
+
+#define _PAGE_SZHUGE_4U _PAGE_SZ4MB_4U
+#define _PAGE_SZHUGE_4V _PAGE_SZ4MB_4V
+
+/* We borrow bit 20 to store the exclusive marker in swap PTEs. */
+#define _PAGE_SWP_EXCLUSIVE _AC(0x0000000000100000, UL)
+
+#ifndef __ASSEMBLY__
+
+pte_t mk_pte_io(unsigned long, pgprot_t, int, unsigned long);
+
+unsigned long pte_sz_bits(unsigned long size);
+
+extern pgprot_t PAGE_KERNEL;
+extern pgprot_t PAGE_KERNEL_LOCKED;
+extern pgprot_t PAGE_COPY;
+extern pgprot_t PAGE_SHARED;
+
+/* XXX This ugliness is for the atyfb driver's sparc mmap() support. XXX */
+extern unsigned long _PAGE_IE;
+extern unsigned long _PAGE_E;
+extern unsigned long _PAGE_CACHE;
+
+extern unsigned long pg_iobits;
+extern unsigned long _PAGE_ALL_SZ_BITS;
+
+extern struct page *mem_map_zero;
+#define ZERO_PAGE(vaddr) (mem_map_zero)
+
+/* PFNs are real physical page numbers. However, mem_map only begins to record
+ * per-page information starting at pfn_base. This is to handle systems where
+ * the first physical page in the machine is at some huge physical address,
+ * such as 4GB. This is common on a partitioned E10000, for example.
+ */
+static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+ unsigned long paddr = pfn << PAGE_SHIFT;
+
+ BUILD_BUG_ON(_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL);
+ return __pte(paddr | pgprot_val(prot));
+}
+#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
+{
+ pte_t pte = pfn_pte(page_nr, pgprot);
+
+ return __pmd(pte_val(pte));
+}
+#define mk_pmd(page, pgprot) pfn_pmd(page_to_pfn(page), (pgprot))
+#endif
+
+/* This one can be done with two shifts. */
+static inline unsigned long pte_pfn(pte_t pte)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__(
+ "\n661: sllx %1, %2, %0\n"
+ " srlx %0, %3, %0\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sllx %1, %4, %0\n"
+ " srlx %0, %5, %0\n"
+ " .previous\n"
+ : "=r" (ret)
+ : "r" (pte_val(pte)),
+ "i" (21), "i" (21 + PAGE_SHIFT),
+ "i" (8), "i" (8 + PAGE_SHIFT));
+
+ return ret;
+}
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t prot)
+{
+ unsigned long mask, tmp;
+
+ /* SUN4U: 0x630107ffffffec38 (negated == 0x9cfef800000013c7)
+ * SUN4V: 0x33ffffffffffee07 (negated == 0xcc000000000011f8)
+ *
+ * Even if we use negation tricks the result is still a 6
+ * instruction sequence, so don't try to play fancy and just
+ * do the most straightforward implementation.
+ *
+ * Note: We encode this into 3 sun4v 2-insn patch sequences.
+ */
+
+ BUILD_BUG_ON(_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL);
+ __asm__ __volatile__(
+ "\n661: sethi %%uhi(%2), %1\n"
+ " sethi %%hi(%2), %0\n"
+ "\n662: or %1, %%ulo(%2), %1\n"
+ " or %0, %%lo(%2), %0\n"
+ "\n663: sllx %1, 32, %1\n"
+ " or %0, %1, %0\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%3), %1\n"
+ " sethi %%hi(%3), %0\n"
+ " .word 662b\n"
+ " or %1, %%ulo(%3), %1\n"
+ " or %0, %%lo(%3), %0\n"
+ " .word 663b\n"
+ " sllx %1, 32, %1\n"
+ " or %0, %1, %0\n"
+ " .previous\n"
+ " .section .sun_m7_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%4), %1\n"
+ " sethi %%hi(%4), %0\n"
+ " .word 662b\n"
+ " or %1, %%ulo(%4), %1\n"
+ " or %0, %%lo(%4), %0\n"
+ " .word 663b\n"
+ " sllx %1, 32, %1\n"
+ " or %0, %1, %0\n"
+ " .previous\n"
+ : "=r" (mask), "=r" (tmp)
+ : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U |
+ _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U |
+ _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U),
+ "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
+ _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V |
+ _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V),
+ "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V |
+ _PAGE_CP_4V | _PAGE_E_4V |
+ _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V));
+
+ return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask));
+}
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ pte = pte_modify(pte, newprot);
+
+ return __pmd(pte_val(pte));
+}
+#endif
+
+static inline pgprot_t pgprot_noncached(pgprot_t prot)
+{
+ unsigned long val = pgprot_val(prot);
+
+ __asm__ __volatile__(
+ "\n661: andn %0, %2, %0\n"
+ " or %0, %3, %0\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " andn %0, %4, %0\n"
+ " or %0, %5, %0\n"
+ " .previous\n"
+ " .section .sun_m7_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " andn %0, %6, %0\n"
+ " or %0, %5, %0\n"
+ " .previous\n"
+ : "=r" (val)
+ : "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U),
+ "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V),
+ "i" (_PAGE_CP_4V));
+
+ return __pgprot(val);
+}
+/* Various pieces of code check for platform support by ifdef testing
+ * on "pgprot_noncached". That's broken and should be fixed, but for
+ * now...
+ */
+#define pgprot_noncached pgprot_noncached
+
+static inline unsigned long pte_dirty(pte_t pte)
+{
+ unsigned long mask;
+
+ __asm__ __volatile__(
+ "\n661: mov %1, %0\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%2), %0\n"
+ " sllx %0, 32, %0\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_MODIFIED_4U), "i" (_PAGE_MODIFIED_4V));
+
+ return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_write(pte_t pte)
+{
+ unsigned long mask;
+
+ __asm__ __volatile__(
+ "\n661: mov %1, %0\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%2), %0\n"
+ " sllx %0, 32, %0\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
+
+ return (pte_val(pte) & mask);
+}
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags);
+#define arch_make_huge_pte arch_make_huge_pte
+static inline unsigned long __pte_default_huge_mask(void)
+{
+ unsigned long mask;
+
+ __asm__ __volatile__(
+ "\n661: sethi %%uhi(%1), %0\n"
+ " sllx %0, 32, %0\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " mov %2, %0\n"
+ " nop\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
+
+ return mask;
+}
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+ return __pte(pte_val(pte) | __pte_default_huge_mask());
+}
+
+static inline bool is_default_hugetlb_pte(pte_t pte)
+{
+ unsigned long mask = __pte_default_huge_mask();
+
+ return (pte_val(pte) & mask) == mask;
+}
+
+static inline bool is_hugetlb_pmd(pmd_t pmd)
+{
+ return !!(pmd_val(pmd) & _PAGE_PMD_HUGE);
+}
+
+static inline bool is_hugetlb_pud(pud_t pud)
+{
+ return !!(pud_val(pud) & _PAGE_PUD_HUGE);
+}
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline pmd_t pmd_mkhuge(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ pte = pte_mkhuge(pte);
+ pte_val(pte) |= _PAGE_PMD_HUGE;
+
+ return __pmd(pte_val(pte));
+}
+#endif
+#else
+static inline bool is_hugetlb_pte(pte_t pte)
+{
+ return false;
+}
+#endif
+
+static inline pte_t __pte_mkhwwrite(pte_t pte)
+{
+ unsigned long val = pte_val(pte);
+
+ /*
+ * Note: we only want to set the HW writable bit if the SW writable bit
+ * and the SW dirty bit are set.
+ */
+ __asm__ __volatile__(
+ "\n661: or %0, %2, %0\n"
+ " .section .sun4v_1insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " or %0, %3, %0\n"
+ " .previous\n"
+ : "=r" (val)
+ : "0" (val), "i" (_PAGE_W_4U), "i" (_PAGE_W_4V));
+
+ return __pte(val);
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+ unsigned long val = pte_val(pte), mask;
+
+ __asm__ __volatile__(
+ "\n661: mov %1, %0\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%2), %0\n"
+ " sllx %0, 32, %0\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_MODIFIED_4U), "i" (_PAGE_MODIFIED_4V));
+
+ pte = __pte(val | mask);
+ return pte_write(pte) ? __pte_mkhwwrite(pte) : pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+ unsigned long val = pte_val(pte), tmp;
+
+ __asm__ __volatile__(
+ "\n661: andn %0, %3, %0\n"
+ " nop\n"
+ "\n662: nop\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%4), %1\n"
+ " sllx %1, 32, %1\n"
+ " .word 662b\n"
+ " or %1, %%lo(%4), %1\n"
+ " andn %0, %1, %0\n"
+ " .previous\n"
+ : "=r" (val), "=r" (tmp)
+ : "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U),
+ "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V));
+
+ return __pte(val);
+}
+
+static inline pte_t pte_mkwrite_novma(pte_t pte)
+{
+ unsigned long val = pte_val(pte), mask;
+
+ __asm__ __volatile__(
+ "\n661: mov %1, %0\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%2), %0\n"
+ " sllx %0, 32, %0\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V));
+
+ pte = __pte(val | mask);
+ return pte_dirty(pte) ? __pte_mkhwwrite(pte) : pte;
+}
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+ unsigned long val = pte_val(pte), tmp;
+
+ __asm__ __volatile__(
+ "\n661: andn %0, %3, %0\n"
+ " nop\n"
+ "\n662: nop\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%4), %1\n"
+ " sllx %1, 32, %1\n"
+ " .word 662b\n"
+ " or %1, %%lo(%4), %1\n"
+ " andn %0, %1, %0\n"
+ " .previous\n"
+ : "=r" (val), "=r" (tmp)
+ : "0" (val), "i" (_PAGE_WRITE_4U | _PAGE_W_4U),
+ "i" (_PAGE_WRITE_4V | _PAGE_W_4V));
+
+ return __pte(val);
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+ unsigned long mask;
+
+ __asm__ __volatile__(
+ "\n661: mov %1, %0\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%2), %0\n"
+ " sllx %0, 32, %0\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+ mask |= _PAGE_R;
+
+ return __pte(pte_val(pte) & ~mask);
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+ unsigned long mask;
+
+ __asm__ __volatile__(
+ "\n661: mov %1, %0\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%2), %0\n"
+ " sllx %0, 32, %0\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+ mask |= _PAGE_R;
+
+ return __pte(pte_val(pte) | mask);
+}
+
+static inline pte_t pte_mkspecial(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_SPECIAL;
+ return pte;
+}
+
+static inline pte_t pte_mkmcd(pte_t pte)
+{
+ pte_val(pte) |= _PAGE_MCD_4V;
+ return pte;
+}
+
+static inline pte_t pte_mknotmcd(pte_t pte)
+{
+ pte_val(pte) &= ~_PAGE_MCD_4V;
+ return pte;
+}
+
+static inline unsigned long pte_young(pte_t pte)
+{
+ unsigned long mask;
+
+ __asm__ __volatile__(
+ "\n661: mov %1, %0\n"
+ " nop\n"
+ " .section .sun4v_2insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " sethi %%uhi(%2), %0\n"
+ " sllx %0, 32, %0\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V));
+
+ return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_exec(pte_t pte)
+{
+ unsigned long mask;
+
+ __asm__ __volatile__(
+ "\n661: sethi %%hi(%1), %0\n"
+ " .section .sun4v_1insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " mov %2, %0\n"
+ " .previous\n"
+ : "=r" (mask)
+ : "i" (_PAGE_EXEC_4U), "i" (_PAGE_EXEC_4V));
+
+ return (pte_val(pte) & mask);
+}
+
+static inline unsigned long pte_present(pte_t pte)
+{
+ unsigned long val = pte_val(pte);
+
+ __asm__ __volatile__(
+ "\n661: and %0, %2, %0\n"
+ " .section .sun4v_1insn_patch, \"ax\"\n"
+ " .word 661b\n"
+ " and %0, %3, %0\n"
+ " .previous\n"
+ : "=r" (val)
+ : "0" (val), "i" (_PAGE_PRESENT_4U), "i" (_PAGE_PRESENT_4V));
+
+ return val;
+}
+
+#define pte_accessible pte_accessible
+static inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a)
+{
+ return pte_val(a) & _PAGE_VALID;
+}
+
+static inline unsigned long pte_special(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_SPECIAL;
+}
+
+#define pmd_leaf pmd_large
+static inline unsigned long pmd_large(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ return pte_val(pte) & _PAGE_PMD_HUGE;
+}
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ return pte_pfn(pte);
+}
+
+#define pmd_write pmd_write
+static inline unsigned long pmd_write(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ return pte_write(pte);
+}
+
+#define pud_write(pud) pte_write(__pte(pud_val(pud)))
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline unsigned long pmd_dirty(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ return pte_dirty(pte);
+}
+
+#define pmd_young pmd_young
+static inline unsigned long pmd_young(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ return pte_young(pte);
+}
+
+static inline unsigned long pmd_trans_huge(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ return pte_val(pte) & _PAGE_PMD_HUGE;
+}
+
+static inline pmd_t pmd_mkold(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ pte = pte_mkold(pte);
+
+ return __pmd(pte_val(pte));
+}
+
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ pte = pte_wrprotect(pte);
+
+ return __pmd(pte_val(pte));
+}
+
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ pte = pte_mkdirty(pte);
+
+ return __pmd(pte_val(pte));
+}
+
+static inline pmd_t pmd_mkclean(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ pte = pte_mkclean(pte);
+
+ return __pmd(pte_val(pte));
+}
+
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ pte = pte_mkyoung(pte);
+
+ return __pmd(pte_val(pte));
+}
+
+static inline pmd_t pmd_mkwrite_novma(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+
+ pte = pte_mkwrite_novma(pte);
+
+ return __pmd(pte_val(pte));
+}
+
+static inline pgprot_t pmd_pgprot(pmd_t entry)
+{
+ unsigned long val = pmd_val(entry);
+
+ return __pgprot(val);
+}
+#endif
+
+static inline int pmd_present(pmd_t pmd)
+{
+ return pmd_val(pmd) != 0UL;
+}
+
+#define pmd_none(pmd) (!pmd_val(pmd))
+
+/* pmd_bad() is only called on non-trans-huge PMDs. Our encoding is
+ * very simple, it's just the physical address. PTE tables are of
+ * size PAGE_SIZE so make sure the sub-PAGE_SIZE bits are clear and
+ * the top bits outside of the range of any physical address size we
+ * support are clear as well. We also validate the physical itself.
+ */
+#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK)
+
+#define pud_none(pud) (!pud_val(pud))
+
+#define pud_bad(pud) (pud_val(pud) & ~PAGE_MASK)
+
+#define p4d_none(p4d) (!p4d_val(p4d))
+
+#define p4d_bad(p4d) (p4d_val(p4d) & ~PAGE_MASK)
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp, pmd_t pmd);
+#else
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+ pmd_t *pmdp, pmd_t pmd)
+{
+ *pmdp = pmd;
+}
+#endif
+
+static inline void pmd_set(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
+{
+ unsigned long val = __pa((unsigned long) (ptep));
+
+ pmd_val(*pmdp) = val;
+}
+
+#define pud_set(pudp, pmdp) \
+ (pud_val(*(pudp)) = (__pa((unsigned long) (pmdp))))
+static inline unsigned long pmd_page_vaddr(pmd_t pmd)
+{
+ pte_t pte = __pte(pmd_val(pmd));
+ unsigned long pfn;
+
+ pfn = pte_pfn(pte);
+
+ return ((unsigned long) __va(pfn << PAGE_SHIFT));
+}
+
+static inline pmd_t *pud_pgtable(pud_t pud)
+{
+ pte_t pte = __pte(pud_val(pud));
+ unsigned long pfn;
+
+ pfn = pte_pfn(pte);
+
+ return ((pmd_t *) __va(pfn << PAGE_SHIFT));
+}
+
+#define pmd_page(pmd) virt_to_page((void *)pmd_page_vaddr(pmd))
+#define pud_page(pud) virt_to_page((void *)pud_pgtable(pud))
+#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL)
+#define pud_present(pud) (pud_val(pud) != 0U)
+#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL)
+#define p4d_pgtable(p4d) \
+ ((pud_t *) __va(p4d_val(p4d)))
+#define p4d_present(p4d) (p4d_val(p4d) != 0U)
+#define p4d_clear(p4dp) (p4d_val(*(p4dp)) = 0UL)
+
+/* only used by the stubbed out hugetlb gup code, should never be called */
+#define p4d_page(p4d) NULL
+
+#define pud_leaf pud_large
+static inline unsigned long pud_large(pud_t pud)
+{
+ pte_t pte = __pte(pud_val(pud));
+
+ return pte_val(pte) & _PAGE_PMD_HUGE;
+}
+
+static inline unsigned long pud_pfn(pud_t pud)
+{
+ pte_t pte = __pte(pud_val(pud));
+
+ return pte_pfn(pte);
+}
+
+/* Same in both SUN4V and SUN4U. */
+#define pte_none(pte) (!pte_val(pte))
+
+#define p4d_set(p4dp, pudp) \
+ (p4d_val(*(p4dp)) = (__pa((unsigned long) (pudp))))
+
+/* We cannot include <linux/mm_types.h> at this point yet: */
+extern struct mm_struct init_mm;
+
+/* Actual page table PTE updates. */
+void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
+ pte_t *ptep, pte_t orig, int fullmm,
+ unsigned int hugepage_shift);
+
+static void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
+ pte_t *ptep, pte_t orig, int fullmm,
+ unsigned int hugepage_shift)
+{
+ /* It is more efficient to let flush_tlb_kernel_range()
+ * handle init_mm tlb flushes.
+ *
+ * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
+ * and SUN4V pte layout, so this inline test is fine.
+ */
+ if (likely(mm != &init_mm) && pte_accessible(mm, orig))
+ tlb_batch_add(mm, vaddr, ptep, orig, fullmm, hugepage_shift);
+}
+
+#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
+static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
+ unsigned long addr,
+ pmd_t *pmdp)
+{
+ pmd_t pmd = *pmdp;
+ set_pmd_at(mm, addr, pmdp, __pmd(0UL));
+ return pmd;
+}
+
+static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte, int fullmm)
+{
+ pte_t orig = *ptep;
+
+ *ptep = pte;
+ maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm, PAGE_SHIFT);
+}
+
+static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte, unsigned int nr)
+{
+ arch_enter_lazy_mmu_mode();
+ for (;;) {
+ __set_pte_at(mm, addr, ptep, pte, 0);
+ if (--nr == 0)
+ break;
+ ptep++;
+ pte_val(pte) += PAGE_SIZE;
+ addr += PAGE_SIZE;
+ }
+ arch_leave_lazy_mmu_mode();
+}
+#define set_ptes set_ptes
+
+#define pte_clear(mm,addr,ptep) \
+ set_pte_at((mm), (addr), (ptep), __pte(0UL))
+
+#define __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL
+#define pte_clear_not_present_full(mm,addr,ptep,fullmm) \
+ __set_pte_at((mm), (addr), (ptep), __pte(0UL), (fullmm))
+
+#ifdef DCACHE_ALIASING_POSSIBLE
+#define __HAVE_ARCH_MOVE_PTE
+#define move_pte(pte, prot, old_addr, new_addr) \
+({ \
+ pte_t newpte = (pte); \
+ if (tlb_type != hypervisor && pte_present(pte)) { \
+ unsigned long this_pfn = pte_pfn(pte); \
+ \
+ if (pfn_valid(this_pfn) && \
+ (((old_addr) ^ (new_addr)) & (1 << 13))) \
+ flush_dcache_folio_all(current->mm, \
+ page_folio(pfn_to_page(this_pfn))); \
+ } \
+ newpte; \
+})
+#endif
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+void paging_init(void);
+unsigned long find_ecache_flush_span(unsigned long size);
+
+struct seq_file;
+void mmu_info(struct seq_file *);
+
+struct vm_area_struct;
+void update_mmu_cache_range(struct vm_fault *, struct vm_area_struct *,
+ unsigned long addr, pte_t *ptep, unsigned int nr);
+#define update_mmu_cache(vma, addr, ptep) \
+ update_mmu_cache_range(NULL, vma, addr, ptep, 1)
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr,
+ pmd_t *pmd);
+
+#define __HAVE_ARCH_PMDP_INVALIDATE
+extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
+ pmd_t *pmdp);
+
+#define __HAVE_ARCH_PGTABLE_DEPOSIT
+void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
+ pgtable_t pgtable);
+
+#define __HAVE_ARCH_PGTABLE_WITHDRAW
+pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
+#endif
+
+/*
+ * Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
+ * are !pte_none() && !pte_present().
+ *
+ * Format of swap PTEs:
+ *
+ * 6 6 6 6 5 5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3
+ * 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2
+ * <--------------------------- offset ---------------------------
+ *
+ * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * --------------------> E <-- type ---> <------- zeroes -------->
+ */
+#define __swp_type(entry) (((entry).val >> PAGE_SHIFT) & 0x7fUL)
+#define __swp_offset(entry) ((entry).val >> (PAGE_SHIFT + 8UL))
+#define __swp_entry(type, offset) \
+ ( (swp_entry_t) \
+ { \
+ ((((long)(type) & 0x7fUL) << PAGE_SHIFT) | \
+ ((long)(offset) << (PAGE_SHIFT + 8UL))) \
+ } )
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+static inline int pte_swp_exclusive(pte_t pte)
+{
+ return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
+}
+
+static inline pte_t pte_swp_mkexclusive(pte_t pte)
+{
+ return __pte(pte_val(pte) | _PAGE_SWP_EXCLUSIVE);
+}
+
+static inline pte_t pte_swp_clear_exclusive(pte_t pte)
+{
+ return __pte(pte_val(pte) & ~_PAGE_SWP_EXCLUSIVE);
+}
+
+int page_in_phys_avail(unsigned long paddr);
+
+/*
+ * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+ * its high 4 bits. These macros/functions put it there or get it from there.
+ */
+#define MK_IOSPACE_PFN(space, pfn) (pfn | (space << (BITS_PER_LONG - 4)))
+#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
+#define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL)
+
+int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+ unsigned long, pgprot_t);
+
+void adi_restore_tags(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long addr, pte_t pte);
+
+int adi_save_tags(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long addr, pte_t oldpte);
+
+#define __HAVE_ARCH_DO_SWAP_PAGE
+static inline void arch_do_swap_page(struct mm_struct *mm,
+ struct vm_area_struct *vma,
+ unsigned long addr,
+ pte_t pte, pte_t oldpte)
+{
+ /* If this is a new page being mapped in, there can be no
+ * ADI tags stored away for this page. Skip looking for
+ * stored tags
+ */
+ if (pte_none(oldpte))
+ return;
+
+ if (adi_state.enabled && (pte_val(pte) & _PAGE_MCD_4V))
+ adi_restore_tags(mm, vma, addr, pte);
+}
+
+#define __HAVE_ARCH_UNMAP_ONE
+static inline int arch_unmap_one(struct mm_struct *mm,
+ struct vm_area_struct *vma,
+ unsigned long addr, pte_t oldpte)
+{
+ if (adi_state.enabled && (pte_val(oldpte) & _PAGE_MCD_4V))
+ return adi_save_tags(mm, vma, addr, oldpte);
+ return 0;
+}
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+ unsigned long from, unsigned long pfn,
+ unsigned long size, pgprot_t prot)
+{
+ unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+ int space = GET_IOSPACE(pfn);
+ unsigned long phys_base;
+
+ phys_base = offset | (((unsigned long) space) << 32UL);
+
+ return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+#define io_remap_pfn_range io_remap_pfn_range
+
+static inline unsigned long __untagged_addr(unsigned long start)
+{
+ if (adi_capable()) {
+ long addr = start;
+
+ /* If userspace has passed a versioned address, kernel
+ * will not find it in the VMAs since it does not store
+ * the version tags in the list of VMAs. Storing version
+ * tags in list of VMAs is impractical since they can be
+ * changed any time from userspace without dropping into
+ * kernel. Any address search in VMAs will be done with
+ * non-versioned addresses. Ensure the ADI version bits
+ * are dropped here by sign extending the last bit before
+ * ADI bits. IOMMU does not implement version tags.
+ */
+ return (addr << (long)adi_nbits()) >> (long)adi_nbits();
+ }
+
+ return start;
+}
+#define untagged_addr(addr) \
+ ((__typeof__(addr))(__untagged_addr((unsigned long)(addr))))
+
+static inline bool pte_access_permitted(pte_t pte, bool write)
+{
+ u64 prot;
+
+ if (tlb_type == hypervisor) {
+ prot = _PAGE_PRESENT_4V | _PAGE_P_4V;
+ if (write)
+ prot |= _PAGE_WRITE_4V;
+ } else {
+ prot = _PAGE_PRESENT_4U | _PAGE_P_4U;
+ if (write)
+ prot |= _PAGE_WRITE_4U;
+ }
+
+ return (pte_val(pte) & (prot | _PAGE_SPECIAL)) == prot;
+}
+#define pte_access_permitted pte_access_permitted
+
+/* We provide our own get_unmapped_area to cope with VA holes and
+ * SHM area cache aliasing for userland.
+ */
+#define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+
+/* We provide a special get_unmapped_area for framebuffer mmaps to try and use
+ * the largest alignment possible such that larget PTEs can be used.
+ */
+unsigned long get_fb_unmapped_area(struct file *filp, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long);
+#define HAVE_ARCH_FB_UNMAPPED_AREA
+
+void sun4v_register_fault_status(void);
+void sun4v_ktsb_register(void);
+void __init cheetah_ecache_flush_init(void);
+void sun4v_patch_tlb_handlers(void);
+
+extern unsigned long cmdline_memory_size;
+
+asmlinkage void do_sparc64_fault(struct pt_regs *regs);
+
+#define pmd_pgtable(PMD) ((pte_t *)pmd_page_vaddr(PMD))
+
+#ifdef CONFIG_HUGETLB_PAGE
+
+#define pud_leaf_size pud_leaf_size
+extern unsigned long pud_leaf_size(pud_t pud);
+
+#define pmd_leaf_size pmd_leaf_size
+extern unsigned long pmd_leaf_size(pmd_t pmd);
+
+#define pte_leaf_size pte_leaf_size
+extern unsigned long pte_leaf_size(pte_t pte);
+
+#endif /* CONFIG_HUGETLB_PAGE */
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_SPARC64_PGTABLE_H) */
diff --git a/arch/sparc/include/asm/pgtsrmmu.h b/arch/sparc/include/asm/pgtsrmmu.h
new file mode 100644
index 000000000..18e68d43f
--- /dev/null
+++ b/arch/sparc/include/asm/pgtsrmmu.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * pgtsrmmu.h: SRMMU page table defines and code.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_PGTSRMMU_H
+#define _SPARC_PGTSRMMU_H
+
+#include <asm/page.h>
+
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h> /* TI_UWINMASK for WINDOW_FLUSH */
+#endif
+
+/* Number of contexts is implementation-dependent; 64k is the most we support */
+#define SRMMU_MAX_CONTEXTS 65536
+
+#define SRMMU_PTE_TABLE_SIZE (PTRS_PER_PTE*4)
+#define SRMMU_PMD_TABLE_SIZE (PTRS_PER_PMD*4)
+#define SRMMU_PGD_TABLE_SIZE (PTRS_PER_PGD*4)
+
+/* Definition of the values in the ET field of PTD's and PTE's */
+#define SRMMU_ET_MASK 0x3
+#define SRMMU_ET_INVALID 0x0
+#define SRMMU_ET_PTD 0x1
+#define SRMMU_ET_PTE 0x2
+#define SRMMU_ET_REPTE 0x3 /* AIEEE, SuperSparc II reverse endian page! */
+
+/* Physical page extraction from PTP's and PTE's. */
+#define SRMMU_CTX_PMASK 0xfffffff0
+#define SRMMU_PTD_PMASK 0xfffffff0
+#define SRMMU_PTE_PMASK 0xffffff00
+
+/* The pte non-page bits. Some notes:
+ * 1) cache, dirty, valid, and ref are frobbable
+ * for both supervisor and user pages.
+ * 2) exec and write will only give the desired effect
+ * on user pages
+ * 3) use priv and priv_readonly for changing the
+ * characteristics of supervisor ptes
+ */
+#define SRMMU_CACHE 0x80
+#define SRMMU_DIRTY 0x40
+#define SRMMU_REF 0x20
+#define SRMMU_NOREAD 0x10
+#define SRMMU_EXEC 0x08
+#define SRMMU_WRITE 0x04
+#define SRMMU_VALID 0x02 /* SRMMU_ET_PTE */
+#define SRMMU_PRIV 0x1c
+#define SRMMU_PRIV_RDONLY 0x18
+
+#define SRMMU_CHG_MASK (0xffffff00 | SRMMU_REF | SRMMU_DIRTY)
+
+/* SRMMU swap entry encoding */
+#define SRMMU_SWP_TYPE_MASK 0x1f
+#define SRMMU_SWP_TYPE_SHIFT 7
+#define SRMMU_SWP_OFF_MASK 0xfffff
+#define SRMMU_SWP_OFF_SHIFT (SRMMU_SWP_TYPE_SHIFT + 5)
+/* We borrow bit 6 to store the exclusive marker in swap PTEs. */
+#define SRMMU_SWP_EXCLUSIVE SRMMU_DIRTY
+
+/* Some day I will implement true fine grained access bits for
+ * user pages because the SRMMU gives us the capabilities to
+ * enforce all the protection levels that vma's can have.
+ * XXX But for now...
+ */
+#define SRMMU_PAGE_NONE __pgprot(SRMMU_CACHE | \
+ SRMMU_PRIV | SRMMU_REF)
+#define SRMMU_PAGE_SHARED __pgprot(SRMMU_VALID | SRMMU_CACHE | \
+ SRMMU_EXEC | SRMMU_WRITE | SRMMU_REF)
+#define SRMMU_PAGE_COPY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
+ SRMMU_EXEC | SRMMU_REF)
+#define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
+ SRMMU_EXEC | SRMMU_REF)
+#define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
+ SRMMU_DIRTY | SRMMU_REF)
+
+/* SRMMU Register addresses in ASI 0x4. These are valid for all
+ * current SRMMU implementations that exist.
+ */
+#define SRMMU_CTRL_REG 0x00000000
+#define SRMMU_CTXTBL_PTR 0x00000100
+#define SRMMU_CTX_REG 0x00000200
+#define SRMMU_FAULT_STATUS 0x00000300
+#define SRMMU_FAULT_ADDR 0x00000400
+
+#define WINDOW_FLUSH(tmp1, tmp2) \
+ mov 0, tmp1; \
+98: ld [%g6 + TI_UWINMASK], tmp2; \
+ orcc %g0, tmp2, %g0; \
+ add tmp1, 1, tmp1; \
+ bne 98b; \
+ save %sp, -64, %sp; \
+99: subcc tmp1, 1, tmp1; \
+ bne 99b; \
+ restore %g0, %g0, %g0;
+
+#ifndef __ASSEMBLY__
+extern unsigned long last_valid_pfn;
+
+/* This makes sense. Honest it does - Anton */
+/* XXX Yes but it's ugly as sin. FIXME. -KMW */
+extern void *srmmu_nocache_pool;
+#define __nocache_pa(VADDR) (((unsigned long)VADDR) - SRMMU_NOCACHE_VADDR + __pa((unsigned long)srmmu_nocache_pool))
+#define __nocache_va(PADDR) (__va((unsigned long)PADDR) - (unsigned long)srmmu_nocache_pool + SRMMU_NOCACHE_VADDR)
+#define __nocache_fix(VADDR) ((__typeof__(VADDR))__va(__nocache_pa(VADDR)))
+
+/* Accessing the MMU control register. */
+unsigned int srmmu_get_mmureg(void);
+void srmmu_set_mmureg(unsigned long regval);
+void srmmu_set_ctable_ptr(unsigned long paddr);
+void srmmu_set_context(int context);
+int srmmu_get_context(void);
+unsigned int srmmu_get_fstatus(void);
+unsigned int srmmu_get_faddr(void);
+
+/* This is guaranteed on all SRMMU's. */
+static inline void srmmu_flush_whole_tlb(void)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
+ "r" (0x400), /* Flush entire TLB!! */
+ "i" (ASI_M_FLUSH_PROBE) : "memory");
+
+}
+
+static inline int
+srmmu_get_pte (unsigned long addr)
+{
+ register unsigned long entry;
+
+ __asm__ __volatile__("\n\tlda [%1] %2,%0\n\t" :
+ "=r" (entry):
+ "r" ((addr & 0xfffff000) | 0x400), "i" (ASI_M_FLUSH_PROBE));
+ return entry;
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_SPARC_PGTSRMMU_H) */
diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h
new file mode 100644
index 000000000..4003c3530
--- /dev/null
+++ b/arch/sparc/include/asm/pil.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_PIL_H
+#define _SPARC64_PIL_H
+
+/* To avoid some locking problems, we hard allocate certain PILs
+ * for SMP cross call messages that must do a etrap/rtrap.
+ *
+ * A local_irq_disable() does not block the cross call delivery, so
+ * when SMP locking is an issue we reschedule the event into a PIL
+ * interrupt which is blocked by local_irq_disable().
+ *
+ * In fact any XCALL which has to etrap/rtrap has a problem because
+ * it is difficult to prevent rtrap from running BH's, and that would
+ * need to be done if the XCALL arrived while %pil==PIL_NORMAL_MAX.
+ *
+ * Finally, in order to handle profiling events even when a
+ * local_irq_disable() is in progress, we only disable up to level 14
+ * interrupts. Profile counter overflow interrupts arrive at level
+ * 15.
+ */
+#define PIL_SMP_CALL_FUNC 1
+#define PIL_SMP_RECEIVE_SIGNAL 2
+#define PIL_SMP_CAPTURE 3
+#define PIL_DEVICE_IRQ 5
+#define PIL_SMP_CALL_FUNC_SNGL 6
+#define PIL_DEFERRED_PCR_WORK 7
+#define PIL_KGDB_CAPTURE 8
+#define PIL_NORMAL_MAX 14
+#define PIL_NMI 15
+
+#endif /* !(_SPARC64_PIL_H) */
diff --git a/arch/sparc/include/asm/processor.h b/arch/sparc/include/asm/processor.h
new file mode 100644
index 000000000..18295ea62
--- /dev/null
+++ b/arch/sparc/include/asm/processor.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_PROCESSOR_H
+#define ___ASM_SPARC_PROCESSOR_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/processor_64.h>
+#else
+#include <asm/processor_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h
new file mode 100644
index 000000000..ba8b70ffe
--- /dev/null
+++ b/arch/sparc/include/asm/processor_32.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* include/asm/processor.h
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __ASM_SPARC_PROCESSOR_H
+#define __ASM_SPARC_PROCESSOR_H
+
+#include <asm/psr.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+#include <asm/signal.h>
+#include <asm/page.h>
+
+/* Whee, this is STACK_TOP + PAGE_SIZE and the lowest kernel address too...
+ * That one page is used to protect kernel from intruders, so that
+ * we can make our access_ok test faster
+ */
+#define TASK_SIZE PAGE_OFFSET
+#ifdef __KERNEL__
+#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
+#define STACK_TOP_MAX STACK_TOP
+#endif /* __KERNEL__ */
+
+struct task_struct;
+
+#ifdef __KERNEL__
+struct fpq {
+ unsigned long *insn_addr;
+ unsigned long insn;
+};
+#endif
+
+/* The Sparc processor specific thread struct. */
+struct thread_struct {
+ struct pt_regs *kregs;
+ unsigned int _pad1;
+
+ /* Special child fork kpsr/kwim values. */
+ unsigned long fork_kpsr __attribute__ ((aligned (8)));
+ unsigned long fork_kwim;
+
+ /* Floating point regs */
+ unsigned long float_regs[32] __attribute__ ((aligned (8)));
+ unsigned long fsr;
+ unsigned long fpqdepth;
+ struct fpq fpqueue[16];
+};
+
+#define INIT_THREAD { \
+ .kregs = (struct pt_regs *)(init_stack+THREAD_SIZE)-1 \
+}
+
+/* Do necessary setup to start up a newly executed thread. */
+static inline void start_thread(struct pt_regs * regs, unsigned long pc,
+ unsigned long sp)
+{
+ register unsigned long zero asm("g1");
+
+ regs->psr = (regs->psr & (PSR_CWP)) | PSR_S;
+ regs->pc = ((pc & (~3)) - 4);
+ regs->npc = regs->pc + 4;
+ regs->y = 0;
+ zero = 0;
+ __asm__ __volatile__("std\t%%g0, [%0 + %3 + 0x00]\n\t"
+ "std\t%%g0, [%0 + %3 + 0x08]\n\t"
+ "std\t%%g0, [%0 + %3 + 0x10]\n\t"
+ "std\t%%g0, [%0 + %3 + 0x18]\n\t"
+ "std\t%%g0, [%0 + %3 + 0x20]\n\t"
+ "std\t%%g0, [%0 + %3 + 0x28]\n\t"
+ "std\t%%g0, [%0 + %3 + 0x30]\n\t"
+ "st\t%1, [%0 + %3 + 0x38]\n\t"
+ "st\t%%g0, [%0 + %3 + 0x3c]"
+ : /* no outputs */
+ : "r" (regs),
+ "r" (sp - sizeof(struct reg_window32)),
+ "r" (zero),
+ "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))
+ : "memory");
+}
+
+unsigned long __get_wchan(struct task_struct *);
+
+#define task_pt_regs(tsk) ((tsk)->thread.kregs)
+#define KSTK_EIP(tsk) ((tsk)->thread.kregs->pc)
+#define KSTK_ESP(tsk) ((tsk)->thread.kregs->u_regs[UREG_FP])
+
+#ifdef __KERNEL__
+
+extern struct task_struct *last_task_used_math;
+int do_mathemu(struct pt_regs *regs, struct task_struct *fpt);
+
+#define cpu_relax() barrier()
+
+extern void (*sparc_idle)(void);
+
+#endif
+
+#endif /* __ASM_SPARC_PROCESSOR_H */
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h
new file mode 100644
index 000000000..0a0d5c3d1
--- /dev/null
+++ b/arch/sparc/include/asm/processor_64.h
@@ -0,0 +1,247 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * include/asm/processor.h
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __ASM_SPARC64_PROCESSOR_H
+#define __ASM_SPARC64_PROCESSOR_H
+
+#include <asm/asi.h>
+#include <asm/pstate.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+
+/*
+ * User lives in his very own context, and cannot reference us. Note
+ * that TASK_SIZE is a misnomer, it really gives maximum user virtual
+ * address that the kernel will allocate out.
+ *
+ * XXX No longer using virtual page tables, kill this upper limit...
+ */
+#define VA_BITS 44
+#ifndef __ASSEMBLY__
+#define VPTE_SIZE (1UL << (VA_BITS - PAGE_SHIFT + 3))
+#else
+#define VPTE_SIZE (1 << (VA_BITS - PAGE_SHIFT + 3))
+#endif
+
+#define TASK_SIZE_OF(tsk) \
+ (test_tsk_thread_flag(tsk,TIF_32BIT) ? \
+ (1UL << 32UL) : ((unsigned long)-VPTE_SIZE))
+#define TASK_SIZE \
+ (test_thread_flag(TIF_32BIT) ? \
+ (1UL << 32UL) : ((unsigned long)-VPTE_SIZE))
+#ifdef __KERNEL__
+
+#define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE)
+#define STACK_TOP64 (0x0000080000000000UL - (1UL << 32UL))
+
+#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+ STACK_TOP32 : STACK_TOP64)
+
+#define STACK_TOP_MAX STACK_TOP64
+
+#endif
+
+#ifndef __ASSEMBLY__
+
+/* The Sparc processor specific thread struct. */
+/* XXX This should die, everything can go into thread_info now. */
+struct thread_struct {
+#ifdef CONFIG_DEBUG_SPINLOCK
+ /* How many spinlocks held by this thread.
+ * Used with spin lock debugging to catch tasks
+ * sleeping illegally with locks held.
+ */
+ int smp_lock_count;
+ unsigned int smp_lock_pc;
+#else
+ int dummy; /* f'in gcc bug... */
+#endif
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#ifndef CONFIG_DEBUG_SPINLOCK
+#define INIT_THREAD { \
+ 0, \
+}
+#else /* CONFIG_DEBUG_SPINLOCK */
+#define INIT_THREAD { \
+/* smp_lock_count, smp_lock_pc, */ \
+ 0, 0, \
+}
+#endif /* !(CONFIG_DEBUG_SPINLOCK) */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+#include <asm/fpumacro.h>
+
+struct task_struct;
+
+/* On Uniprocessor, even in RMO processes see TSO semantics */
+#ifdef CONFIG_SMP
+#define TSTATE_INITIAL_MM TSTATE_TSO
+#else
+#define TSTATE_INITIAL_MM TSTATE_RMO
+#endif
+
+/* Do necessary setup to start up a newly executed thread. */
+#define start_thread(regs, pc, sp) \
+do { \
+ unsigned long __asi = ASI_PNF; \
+ regs->tstate = (regs->tstate & (TSTATE_CWP)) | (TSTATE_INITIAL_MM|TSTATE_IE) | (__asi << 24UL); \
+ regs->tpc = ((pc & (~3)) - 4); \
+ regs->tnpc = regs->tpc + 4; \
+ regs->y = 0; \
+ set_thread_wstate(1 << 3); \
+ if (current_thread_info()->utraps) { \
+ if (*(current_thread_info()->utraps) < 2) \
+ kfree(current_thread_info()->utraps); \
+ else \
+ (*(current_thread_info()->utraps))--; \
+ current_thread_info()->utraps = NULL; \
+ } \
+ __asm__ __volatile__( \
+ "stx %%g0, [%0 + %2 + 0x00]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x08]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x10]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x18]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x20]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x28]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x30]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x38]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x40]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x48]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x50]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x58]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x60]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x68]\n\t" \
+ "stx %1, [%0 + %2 + 0x70]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x78]\n\t" \
+ "wrpr %%g0, (1 << 3), %%wstate\n\t" \
+ : \
+ : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \
+ "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
+ fprs_write(0); \
+ current_thread_info()->xfsr[0] = 0; \
+ current_thread_info()->fpsaved[0] = 0; \
+ regs->tstate &= ~TSTATE_PEF; \
+} while (0)
+
+#define start_thread32(regs, pc, sp) \
+do { \
+ unsigned long __asi = ASI_PNF; \
+ pc &= 0x00000000ffffffffUL; \
+ sp &= 0x00000000ffffffffUL; \
+ regs->tstate = (regs->tstate & (TSTATE_CWP))|(TSTATE_INITIAL_MM|TSTATE_IE|TSTATE_AM) | (__asi << 24UL); \
+ regs->tpc = ((pc & (~3)) - 4); \
+ regs->tnpc = regs->tpc + 4; \
+ regs->y = 0; \
+ set_thread_wstate(2 << 3); \
+ if (current_thread_info()->utraps) { \
+ if (*(current_thread_info()->utraps) < 2) \
+ kfree(current_thread_info()->utraps); \
+ else \
+ (*(current_thread_info()->utraps))--; \
+ current_thread_info()->utraps = NULL; \
+ } \
+ __asm__ __volatile__( \
+ "stx %%g0, [%0 + %2 + 0x00]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x08]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x10]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x18]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x20]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x28]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x30]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x38]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x40]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x48]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x50]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x58]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x60]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x68]\n\t" \
+ "stx %1, [%0 + %2 + 0x70]\n\t" \
+ "stx %%g0, [%0 + %2 + 0x78]\n\t" \
+ "wrpr %%g0, (2 << 3), %%wstate\n\t" \
+ : \
+ : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \
+ "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
+ fprs_write(0); \
+ current_thread_info()->xfsr[0] = 0; \
+ current_thread_info()->fpsaved[0] = 0; \
+ regs->tstate &= ~TSTATE_PEF; \
+} while (0)
+
+unsigned long __get_wchan(struct task_struct *task);
+
+#define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
+#define KSTK_EIP(tsk) (task_pt_regs(tsk)->tpc)
+#define KSTK_ESP(tsk) (task_pt_regs(tsk)->u_regs[UREG_FP])
+
+/* Please see the commentary in asm/backoff.h for a description of
+ * what these instructions are doing and how they have been chosen.
+ * To make a long story short, we are trying to yield the current cpu
+ * strand during busy loops.
+ */
+#ifdef BUILD_VDSO
+#define cpu_relax() asm volatile("\n99:\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ ::: "memory")
+#else /* ! BUILD_VDSO */
+#define cpu_relax() asm volatile("\n99:\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ "rd %%ccr, %%g0\n\t" \
+ ".section .pause_3insn_patch,\"ax\"\n\t"\
+ ".word 99b\n\t" \
+ "wr %%g0, 128, %%asr27\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ ".previous" \
+ ::: "memory")
+#endif
+
+/* Prefetch support. This is tuned for UltraSPARC-III and later.
+ * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
+ * a shallower prefetch queue than later chips.
+ */
+#define ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCHW
+
+static inline void prefetch(const void *x)
+{
+ /* We do not use the read prefetch mnemonic because that
+ * prefetches into the prefetch-cache which only is accessible
+ * by floating point operations in UltraSPARC-III and later.
+ * By contrast, "#one_write" prefetches into the L2 cache
+ * in shared state.
+ */
+ __asm__ __volatile__("prefetch [%0], #one_write"
+ : /* no outputs */
+ : "r" (x));
+}
+
+static inline void prefetchw(const void *x)
+{
+ /* The most optimal prefetch to use for writes is
+ * "#n_writes". This brings the cacheline into the
+ * L2 cache in "owned" state.
+ */
+ __asm__ __volatile__("prefetch [%0], #n_writes"
+ : /* no outputs */
+ : "r" (x));
+}
+
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
+int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap);
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__ASM_SPARC64_PROCESSOR_H) */
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h
new file mode 100644
index 000000000..8184575b1
--- /dev/null
+++ b/arch/sparc/include/asm/prom.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <linux/of.h> /* linux/of.h gets to determine #include ordering */
+#ifndef _SPARC_PROM_H
+#define _SPARC_PROM_H
+#ifdef __KERNEL__
+
+/*
+ * Definitions for talking to the Open Firmware PROM on
+ * Power Macintosh computers.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
+ * Updates for SPARC by David S. Miller
+ */
+#include <linux/types.h>
+#include <linux/of_pdt.h>
+#include <linux/proc_fs.h>
+#include <linux/mutex.h>
+#include <linux/atomic.h>
+#include <linux/irqdomain.h>
+#include <linux/spinlock.h>
+
+#define of_compat_cmp(s1, s2, l) strncmp((s1), (s2), (l))
+#define of_prop_cmp(s1, s2) strcasecmp((s1), (s2))
+#define of_node_cmp(s1, s2) strcmp((s1), (s2))
+
+extern raw_spinlock_t devtree_lock;
+
+struct of_irq_controller {
+ unsigned int (*irq_build)(struct device_node *, unsigned int, void *);
+ void *data;
+};
+
+struct device_node *of_find_node_by_cpuid(int cpuid);
+int of_set_property(struct device_node *node, const char *name, void *val, int len);
+extern struct mutex of_set_property_mutex;
+int of_getintprop_default(struct device_node *np,
+ const char *name,
+ int def);
+int of_find_in_proplist(const char *list, const char *match, int len);
+
+void prom_build_devicetree(void);
+void of_populate_present_mask(void);
+void of_fill_in_cpu_data(void);
+
+struct resource;
+void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
+void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
+
+extern struct device_node *of_console_device;
+extern char *of_console_path;
+extern char *of_console_options;
+
+void irq_trans_init(struct device_node *dp);
+char *build_path_component(struct device_node *dp);
+
+#endif /* __KERNEL__ */
+#endif /* _SPARC_PROM_H */
diff --git a/arch/sparc/include/asm/psr.h b/arch/sparc/include/asm/psr.h
new file mode 100644
index 000000000..65127ce56
--- /dev/null
+++ b/arch/sparc/include/asm/psr.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * psr.h: This file holds the macros for masking off various parts of
+ * the processor status register on the Sparc. This is valid
+ * for Version 8. On the V9 this is renamed to the PSTATE
+ * register and its members are accessed as fields like
+ * PSTATE.PRIV for the current CPU privilege level.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef __LINUX_SPARC_PSR_H
+#define __LINUX_SPARC_PSR_H
+
+#include <uapi/asm/psr.h>
+
+
+#ifndef __ASSEMBLY__
+/* Get the %psr register. */
+static inline unsigned int get_psr(void)
+{
+ unsigned int psr;
+ __asm__ __volatile__(
+ "rd %%psr, %0\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ : "=r" (psr)
+ : /* no inputs */
+ : "memory");
+
+ return psr;
+}
+
+static inline void put_psr(unsigned int new_psr)
+{
+ __asm__ __volatile__(
+ "wr %0, 0x0, %%psr\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ : /* no outputs */
+ : "r" (new_psr)
+ : "memory", "cc");
+}
+
+/* Get the %fsr register. Be careful, make sure the floating point
+ * enable bit is set in the %psr when you execute this or you will
+ * incur a trap.
+ */
+
+extern unsigned int fsr_storage;
+
+static inline unsigned int get_fsr(void)
+{
+ unsigned int fsr = 0;
+
+ __asm__ __volatile__(
+ "st %%fsr, %1\n\t"
+ "ld %1, %0\n\t"
+ : "=r" (fsr)
+ : "m" (fsr_storage));
+
+ return fsr;
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__LINUX_SPARC_PSR_H) */
diff --git a/arch/sparc/include/asm/ptrace.h b/arch/sparc/include/asm/ptrace.h
new file mode 100644
index 000000000..d1419e669
--- /dev/null
+++ b/arch/sparc/include/asm/ptrace.h
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_PTRACE_H
+#define __SPARC_PTRACE_H
+
+#include <uapi/asm/ptrace.h>
+
+#if defined(__sparc__) && defined(__arch64__)
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler.h>
+#include <linux/threads.h>
+#include <asm/switch_to.h>
+
+static inline int pt_regs_trap_type(struct pt_regs *regs)
+{
+ return regs->magic & 0x1ff;
+}
+
+static inline bool pt_regs_is_syscall(struct pt_regs *regs)
+{
+ return (regs->tstate & TSTATE_SYSCALL);
+}
+
+static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
+{
+ return (regs->tstate &= ~TSTATE_SYSCALL);
+}
+
+#define arch_ptrace_stop_needed() \
+({ flush_user_windows(); \
+ get_thread_wsaved() != 0; \
+})
+
+#define arch_ptrace_stop() \
+ synchronize_user_stack()
+
+#define current_pt_regs() \
+ ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
+struct global_reg_snapshot {
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned long o7;
+ unsigned long i7;
+ unsigned long rpc;
+ struct thread_info *thread;
+ unsigned long pad1;
+};
+
+struct global_pmu_snapshot {
+ unsigned long pcr[4];
+ unsigned long pic[4];
+};
+
+union global_cpu_snapshot {
+ struct global_reg_snapshot reg;
+ struct global_pmu_snapshot pmu;
+};
+
+extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
+
+#define force_successful_syscall_return() set_thread_noerror(1)
+#define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
+#define instruction_pointer(regs) ((regs)->tpc)
+#define instruction_pointer_set(regs, val) do { \
+ (regs)->tpc = (val); \
+ (regs)->tnpc = (val)+4; \
+ } while (0)
+#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+ return !(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY));
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+ return regs->u_regs[UREG_I0];
+}
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
+
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, magic))
+
+int regs_query_register_offset(const char *name);
+unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n);
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs: pt_regs from which register value is gotten
+ * @offset: offset number of the register.
+ *
+ * regs_get_register returns the value of a register whose
+ * offset from @regs. The @offset is the offset of the register
+ * in struct pt_regs. If @offset is bigger than MAX_REG_OFFSET,
+ * this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+ unsigned long offset)
+{
+ if (unlikely(offset >= MAX_REG_OFFSET))
+ return 0;
+ if (offset == PT_V9_Y)
+ return *(unsigned int *)((unsigned long)regs + offset);
+ return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+/* Valid only for Kernel mode traps. */
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+ return regs->u_regs[UREG_I6];
+}
+#else /* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
+#else /* (defined(__sparc__) && defined(__arch64__)) */
+#ifndef __ASSEMBLY__
+#include <asm/switch_to.h>
+
+static inline bool pt_regs_is_syscall(struct pt_regs *regs)
+{
+ return (regs->psr & PSR_SYSCALL);
+}
+
+static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
+{
+ return (regs->psr &= ~PSR_SYSCALL);
+}
+
+#define arch_ptrace_stop_needed() \
+({ flush_user_windows(); \
+ current_thread_info()->w_saved != 0; \
+})
+
+#define arch_ptrace_stop() \
+ synchronize_user_stack()
+
+#define current_pt_regs() \
+ ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
+
+#define user_mode(regs) (!((regs)->psr & PSR_PS))
+#define instruction_pointer(regs) ((regs)->pc)
+#define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
+unsigned long profile_pc(struct pt_regs *);
+#else /* (!__ASSEMBLY__) */
+#endif /* (!__ASSEMBLY__) */
+#endif /* (defined(__sparc__) && defined(__arch64__)) */
+#define STACK_BIAS 2047
+
+/* global_reg_snapshot offsets */
+#define GR_SNAP_TSTATE 0x00
+#define GR_SNAP_TPC 0x08
+#define GR_SNAP_TNPC 0x10
+#define GR_SNAP_O7 0x18
+#define GR_SNAP_I7 0x20
+#define GR_SNAP_RPC 0x28
+#define GR_SNAP_THREAD 0x30
+#define GR_SNAP_PAD1 0x38
+
+#endif /* !(__SPARC_PTRACE_H) */
diff --git a/arch/sparc/include/asm/qrwlock.h b/arch/sparc/include/asm/qrwlock.h
new file mode 100644
index 000000000..c27772915
--- /dev/null
+++ b/arch/sparc/include/asm/qrwlock.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC_QRWLOCK_H
+#define _ASM_SPARC_QRWLOCK_H
+
+#include <asm-generic/qrwlock_types.h>
+#include <asm-generic/qrwlock.h>
+
+#endif /* _ASM_SPARC_QRWLOCK_H */
diff --git a/arch/sparc/include/asm/qspinlock.h b/arch/sparc/include/asm/qspinlock.h
new file mode 100644
index 000000000..48808f3d9
--- /dev/null
+++ b/arch/sparc/include/asm/qspinlock.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC_QSPINLOCK_H
+#define _ASM_SPARC_QSPINLOCK_H
+
+#include <asm-generic/qspinlock_types.h>
+#include <asm-generic/qspinlock.h>
+
+#endif /* _ASM_SPARC_QSPINLOCK_H */
diff --git a/arch/sparc/include/asm/ross.h b/arch/sparc/include/asm/ross.h
new file mode 100644
index 000000000..79a54d66a
--- /dev/null
+++ b/arch/sparc/include/asm/ross.h
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ross.h: Ross module specific definitions and defines.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_ROSS_H
+#define _SPARC_ROSS_H
+
+#include <asm/asi.h>
+#include <asm/page.h>
+
+/* Ross made Hypersparcs have a %psr 'impl' field of '0001'. The 'vers'
+ * field has '1111'.
+ */
+
+/* The MMU control register fields on the HyperSparc.
+ *
+ * -----------------------------------------------------------------
+ * |implvers| RSV |CWR|SE|WBE| MID |BM| C|CS|MR|CM|RSV|CE|RSV|NF|ME|
+ * -----------------------------------------------------------------
+ * 31 24 23-22 21 20 19 18-15 14 13 12 11 10 9 8 7-2 1 0
+ *
+ * Phew, lots of fields there ;-)
+ *
+ * CWR: Cache Wrapping Enabled, if one cache wrapping is on.
+ * SE: Snoop Enable, turns on bus snooping for cache activity if one.
+ * WBE: Write Buffer Enable, one turns it on.
+ * MID: The ModuleID of the chip for MBus transactions.
+ * BM: Boot-Mode. One indicates the MMU is in boot mode.
+ * C: Indicates whether accesses are cachable while the MMU is
+ * disabled.
+ * CS: Cache Size -- 0 = 128k, 1 = 256k
+ * MR: Memory Reflection, one indicates that the memory bus connected
+ * to the MBus supports memory reflection.
+ * CM: Cache Mode -- 0 = write-through, 1 = copy-back
+ * CE: Cache Enable -- 0 = no caching, 1 = cache is on
+ * NF: No Fault -- 0 = faults trap the CPU from supervisor mode
+ * 1 = faults from supervisor mode do not generate traps
+ * ME: MMU Enable -- 0 = MMU is off, 1 = MMU is on
+ */
+
+#define HYPERSPARC_CWENABLE 0x00200000
+#define HYPERSPARC_SBENABLE 0x00100000
+#define HYPERSPARC_WBENABLE 0x00080000
+#define HYPERSPARC_MIDMASK 0x00078000
+#define HYPERSPARC_BMODE 0x00004000
+#define HYPERSPARC_ACENABLE 0x00002000
+#define HYPERSPARC_CSIZE 0x00001000
+#define HYPERSPARC_MRFLCT 0x00000800
+#define HYPERSPARC_CMODE 0x00000400
+#define HYPERSPARC_CENABLE 0x00000100
+#define HYPERSPARC_NFAULT 0x00000002
+#define HYPERSPARC_MENABLE 0x00000001
+
+
+/* The ICCR instruction cache register on the HyperSparc.
+ *
+ * -----------------------------------------------
+ * | | FTD | ICE |
+ * -----------------------------------------------
+ * 31 1 0
+ *
+ * This register is accessed using the V8 'wrasr' and 'rdasr'
+ * opcodes, since not all assemblers understand them and those
+ * that do use different semantics I will just hard code the
+ * instruction with a '.word' statement.
+ *
+ * FTD: If set to one flush instructions executed during an
+ * instruction cache hit occurs, the corresponding line
+ * for said cache-hit is invalidated. If FTD is zero,
+ * an unimplemented 'flush' trap will occur when any
+ * flush is executed by the processor.
+ *
+ * ICE: If set to one, the instruction cache is enabled. If
+ * zero, the cache will not be used for instruction fetches.
+ *
+ * All other bits are read as zeros, and writes to them have no
+ * effect.
+ *
+ * Wheee, not many assemblers understand the %iccr register nor
+ * the generic asr r/w instructions.
+ *
+ * 1000 0011 0100 0111 1100 0000 0000 0000 ! rd %iccr, %g1
+ *
+ * 0x 8 3 4 7 c 0 0 0 ! 0x8347c000
+ *
+ * 1011 1111 1000 0000 0110 0000 0000 0000 ! wr %g1, 0x0, %iccr
+ *
+ * 0x b f 8 0 6 0 0 0 ! 0xbf806000
+ *
+ */
+
+#define HYPERSPARC_ICCR_FTD 0x00000002
+#define HYPERSPARC_ICCR_ICE 0x00000001
+
+#ifndef __ASSEMBLY__
+
+static inline unsigned int get_ross_icr(void)
+{
+ unsigned int icreg;
+
+ __asm__ __volatile__(".word 0x8347c000\n\t" /* rd %iccr, %g1 */
+ "mov %%g1, %0\n\t"
+ : "=r" (icreg)
+ : /* no inputs */
+ : "g1", "memory");
+
+ return icreg;
+}
+
+static inline void put_ross_icr(unsigned int icreg)
+{
+ __asm__ __volatile__("or %%g0, %0, %%g1\n\t"
+ ".word 0xbf806000\n\t" /* wr %g1, 0x0, %iccr */
+ "nop\n\t"
+ "nop\n\t"
+ "nop\n\t"
+ : /* no outputs */
+ : "r" (icreg)
+ : "g1", "memory");
+
+ return;
+}
+
+/* HyperSparc specific cache flushing. */
+
+/* This is for the on-chip instruction cache. */
+static inline void hyper_flush_whole_icache(void)
+{
+ __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"
+ : /* no outputs */
+ : "i" (ASI_M_FLUSH_IWHOLE)
+ : "memory");
+ return;
+}
+
+extern int vac_cache_size;
+extern int vac_line_size;
+
+static inline void hyper_clear_all_tags(void)
+{
+ unsigned long addr;
+
+ for(addr = 0; addr < vac_cache_size; addr += vac_line_size)
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_DATAC_TAG)
+ : "memory");
+}
+
+static inline void hyper_flush_unconditional_combined(void)
+{
+ unsigned long addr;
+
+ for (addr = 0; addr < vac_cache_size; addr += vac_line_size)
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_FLUSH_CTX)
+ : "memory");
+}
+
+static inline void hyper_flush_cache_user(void)
+{
+ unsigned long addr;
+
+ for (addr = 0; addr < vac_cache_size; addr += vac_line_size)
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_FLUSH_USER)
+ : "memory");
+}
+
+static inline void hyper_flush_cache_page(unsigned long page)
+{
+ unsigned long end;
+
+ page &= PAGE_MASK;
+ end = page + PAGE_SIZE;
+ while (page < end) {
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (page), "i" (ASI_M_FLUSH_PAGE)
+ : "memory");
+ page += vac_line_size;
+ }
+}
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_SPARC_ROSS_H) */
diff --git a/arch/sparc/include/asm/sbi.h b/arch/sparc/include/asm/sbi.h
new file mode 100644
index 000000000..4d6026c1e
--- /dev/null
+++ b/arch/sparc/include/asm/sbi.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * sbi.h: SBI (Sbus Interface on sun4d) definitions
+ *
+ * Copyright (C) 1997 Jakub Jelinek <jj@sunsite.mff.cuni.cz>
+ */
+
+#ifndef _SPARC_SBI_H
+#define _SPARC_SBI_H
+
+#include <asm/obio.h>
+
+/* SBI */
+struct sbi_regs {
+/* 0x0000 */ u32 cid; /* Component ID */
+/* 0x0004 */ u32 ctl; /* Control */
+/* 0x0008 */ u32 status; /* Status */
+ u32 _unused1;
+
+/* 0x0010 */ u32 cfg0; /* Slot0 config reg */
+/* 0x0014 */ u32 cfg1; /* Slot1 config reg */
+/* 0x0018 */ u32 cfg2; /* Slot2 config reg */
+/* 0x001c */ u32 cfg3; /* Slot3 config reg */
+
+/* 0x0020 */ u32 stb0; /* Streaming buf control for slot 0 */
+/* 0x0024 */ u32 stb1; /* Streaming buf control for slot 1 */
+/* 0x0028 */ u32 stb2; /* Streaming buf control for slot 2 */
+/* 0x002c */ u32 stb3; /* Streaming buf control for slot 3 */
+
+/* 0x0030 */ u32 intr_state; /* Interrupt state */
+/* 0x0034 */ u32 intr_tid; /* Interrupt target ID */
+/* 0x0038 */ u32 intr_diag; /* Interrupt diagnostics */
+};
+
+#define SBI_CID 0x02800000
+#define SBI_CTL 0x02800004
+#define SBI_STATUS 0x02800008
+#define SBI_CFG0 0x02800010
+#define SBI_CFG1 0x02800014
+#define SBI_CFG2 0x02800018
+#define SBI_CFG3 0x0280001c
+#define SBI_STB0 0x02800020
+#define SBI_STB1 0x02800024
+#define SBI_STB2 0x02800028
+#define SBI_STB3 0x0280002c
+#define SBI_INTR_STATE 0x02800030
+#define SBI_INTR_TID 0x02800034
+#define SBI_INTR_DIAG 0x02800038
+
+/* Burst bits for 8, 16, 32, 64 are in cfgX registers at bits 2, 3, 4, 5 respectively */
+#define SBI_CFG_BURST_MASK 0x0000001e
+
+/* How to make devid from sbi no */
+#define SBI2DEVID(sbino) ((sbino<<4)|2)
+
+/* intr_state has 4 bits for slots 0 .. 3 and these bits are repeated for each sbus irq level
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * SBUS IRQ LEVEL | 7 | 6 | 5 | 4 | 3 | 2 | 1 | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Reser |
+ * SLOT # |3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0|3|2|1|0| ved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------+
+ * Bits 31 27 23 19 15 11 7 3 0
+ */
+
+
+#ifndef __ASSEMBLY__
+
+static inline int acquire_sbi(int devid, int mask)
+{
+ __asm__ __volatile__ ("swapa [%2] %3, %0" :
+ "=r" (mask) :
+ "0" (mask),
+ "r" (ECSR_DEV_BASE(devid) | SBI_INTR_STATE),
+ "i" (ASI_M_CTL));
+ return mask;
+}
+
+static inline void release_sbi(int devid, int mask)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (mask),
+ "r" (ECSR_DEV_BASE(devid) | SBI_INTR_STATE),
+ "i" (ASI_M_CTL));
+}
+
+static inline void set_sbi_tid(int devid, int targetid)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (targetid),
+ "r" (ECSR_DEV_BASE(devid) | SBI_INTR_TID),
+ "i" (ASI_M_CTL));
+}
+
+static inline int get_sbi_ctl(int devid, int cfgno)
+{
+ int cfg;
+
+ __asm__ __volatile__ ("lda [%1] %2, %0" :
+ "=r" (cfg) :
+ "r" ((ECSR_DEV_BASE(devid) | SBI_CFG0) + (cfgno<<2)),
+ "i" (ASI_M_CTL));
+ return cfg;
+}
+
+static inline void set_sbi_ctl(int devid, int cfgno, int cfg)
+{
+ __asm__ __volatile__ ("sta %0, [%1] %2" : :
+ "r" (cfg),
+ "r" ((ECSR_DEV_BASE(devid) | SBI_CFG0) + (cfgno<<2)),
+ "i" (ASI_M_CTL));
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !(_SPARC_SBI_H) */
diff --git a/arch/sparc/include/asm/scratchpad.h b/arch/sparc/include/asm/scratchpad.h
new file mode 100644
index 000000000..958351190
--- /dev/null
+++ b/arch/sparc/include/asm/scratchpad.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_SCRATCHPAD_H
+#define _SPARC64_SCRATCHPAD_H
+
+/* Sun4v scratchpad registers, accessed via ASI_SCRATCHPAD. */
+
+#define SCRATCHPAD_MMU_MISS 0x00 /* Shared with OBP - set by OBP */
+#define SCRATCHPAD_CPUID 0x08 /* Shared with OBP - set by hypervisor */
+#define SCRATCHPAD_UTSBREG1 0x10
+#define SCRATCHPAD_UTSBREG2 0x18
+ /* 0x20 and 0x28, hypervisor only... */
+#define SCRATCHPAD_UNUSED1 0x30
+#define SCRATCHPAD_UNUSED2 0x38 /* Reserved for OBP */
+
+#endif /* !(_SPARC64_SCRATCHPAD_H) */
diff --git a/arch/sparc/include/asm/seccomp.h b/arch/sparc/include/asm/seccomp.h
new file mode 100644
index 000000000..62d4579ef
--- /dev/null
+++ b/arch/sparc/include/asm/seccomp.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SECCOMP_H
+#define _ASM_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_sigreturn_32 __NR_sigreturn
+
+#include <asm-generic/seccomp.h>
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/arch/sparc/include/asm/sections.h b/arch/sparc/include/asm/sections.h
new file mode 100644
index 000000000..08f833453
--- /dev/null
+++ b/arch/sparc/include/asm/sections.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_SECTIONS_H
+#define __SPARC_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+/* sparc entry point */
+extern char _start[];
+
+extern char __leon_1insn_patch[];
+extern char __leon_1insn_patch_end[];
+
+#endif
diff --git a/arch/sparc/include/asm/setup.h b/arch/sparc/include/asm/setup.h
new file mode 100644
index 000000000..72205684e
--- /dev/null
+++ b/arch/sparc/include/asm/setup.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Just a place holder.
+ */
+#ifndef _SPARC_SETUP_H
+#define _SPARC_SETUP_H
+
+#include <linux/interrupt.h>
+
+#include <uapi/asm/setup.h>
+
+extern char reboot_command[];
+
+#ifdef CONFIG_SPARC32
+/* The CPU that was used for booting
+ * Only sun4d + leon may have boot_cpu_id != 0
+ */
+extern unsigned char boot_cpu_id;
+
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
+
+extern int serial_console;
+static inline int con_is_present(void)
+{
+ return serial_console ? 0 : 1;
+}
+
+/* from irq_32.c */
+extern volatile unsigned char *fdc_status;
+extern char *pdma_vaddr;
+extern unsigned long pdma_size;
+extern volatile int doing_pdma;
+
+/* This is software state */
+extern char *pdma_base;
+extern unsigned long pdma_areasize;
+
+int sparc_floppy_request_irq(unsigned int irq, irq_handler_t irq_handler);
+
+/* setup_32.c */
+extern unsigned long cmdline_memory_size;
+
+/* devices.c */
+void __init device_scan(void);
+
+/* unaligned_32.c */
+unsigned long safe_compute_effective_address(struct pt_regs *, unsigned int);
+
+#endif
+
+#ifdef CONFIG_SPARC64
+void __init start_early_boot(void);
+
+/* unaligned_64.c */
+int handle_ldf_stq(u32 insn, struct pt_regs *regs);
+void handle_ld_nf(u32 insn, struct pt_regs *regs);
+
+/* init_64.c */
+extern atomic_t dcpage_flushes;
+extern atomic_t dcpage_flushes_xcall;
+
+extern int sysctl_tsb_ratio;
+
+#ifdef CONFIG_SERIAL_SUNHV
+void sunhv_migrate_hvcons_irq(int cpu);
+#endif
+#endif
+void sun_do_break(void);
+extern int stop_a_enabled;
+extern int scons_pwroff;
+
+#endif /* _SPARC_SETUP_H */
diff --git a/arch/sparc/include/asm/sfafsr.h b/arch/sparc/include/asm/sfafsr.h
new file mode 100644
index 000000000..9c98f4fc8
--- /dev/null
+++ b/arch/sparc/include/asm/sfafsr.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_SFAFSR_H
+#define _SPARC64_SFAFSR_H
+
+#include <linux/const.h>
+
+/* Spitfire Asynchronous Fault Status register, ASI=0x4C VA<63:0>=0x0 */
+
+#define SFAFSR_ME (_AC(1,UL) << SFAFSR_ME_SHIFT)
+#define SFAFSR_ME_SHIFT 32
+#define SFAFSR_PRIV (_AC(1,UL) << SFAFSR_PRIV_SHIFT)
+#define SFAFSR_PRIV_SHIFT 31
+#define SFAFSR_ISAP (_AC(1,UL) << SFAFSR_ISAP_SHIFT)
+#define SFAFSR_ISAP_SHIFT 30
+#define SFAFSR_ETP (_AC(1,UL) << SFAFSR_ETP_SHIFT)
+#define SFAFSR_ETP_SHIFT 29
+#define SFAFSR_IVUE (_AC(1,UL) << SFAFSR_IVUE_SHIFT)
+#define SFAFSR_IVUE_SHIFT 28
+#define SFAFSR_TO (_AC(1,UL) << SFAFSR_TO_SHIFT)
+#define SFAFSR_TO_SHIFT 27
+#define SFAFSR_BERR (_AC(1,UL) << SFAFSR_BERR_SHIFT)
+#define SFAFSR_BERR_SHIFT 26
+#define SFAFSR_LDP (_AC(1,UL) << SFAFSR_LDP_SHIFT)
+#define SFAFSR_LDP_SHIFT 25
+#define SFAFSR_CP (_AC(1,UL) << SFAFSR_CP_SHIFT)
+#define SFAFSR_CP_SHIFT 24
+#define SFAFSR_WP (_AC(1,UL) << SFAFSR_WP_SHIFT)
+#define SFAFSR_WP_SHIFT 23
+#define SFAFSR_EDP (_AC(1,UL) << SFAFSR_EDP_SHIFT)
+#define SFAFSR_EDP_SHIFT 22
+#define SFAFSR_UE (_AC(1,UL) << SFAFSR_UE_SHIFT)
+#define SFAFSR_UE_SHIFT 21
+#define SFAFSR_CE (_AC(1,UL) << SFAFSR_CE_SHIFT)
+#define SFAFSR_CE_SHIFT 20
+#define SFAFSR_ETS (_AC(0xf,UL) << SFAFSR_ETS_SHIFT)
+#define SFAFSR_ETS_SHIFT 16
+#define SFAFSR_PSYND (_AC(0xffff,UL) << SFAFSR_PSYND_SHIFT)
+#define SFAFSR_PSYND_SHIFT 0
+
+/* UDB Error Register, ASI=0x7f VA<63:0>=0x0(High),0x18(Low) for read
+ * ASI=0x77 VA<63:0>=0x0(High),0x18(Low) for write
+ */
+
+#define UDBE_UE (_AC(1,UL) << 9)
+#define UDBE_CE (_AC(1,UL) << 8)
+#define UDBE_E_SYNDR (_AC(0xff,UL) << 0)
+
+/* The trap handlers for asynchronous errors encode the AFSR and
+ * other pieces of information into a 64-bit argument for C code
+ * encoded as follows:
+ *
+ * -----------------------------------------------
+ * | UDB_H | UDB_L | TL>1 | TT | AFSR |
+ * -----------------------------------------------
+ * 63 54 53 44 42 41 33 32 0
+ *
+ * The AFAR is passed in unchanged.
+ */
+#define SFSTAT_UDBH_MASK (_AC(0x3ff,UL) << SFSTAT_UDBH_SHIFT)
+#define SFSTAT_UDBH_SHIFT 54
+#define SFSTAT_UDBL_MASK (_AC(0x3ff,UL) << SFSTAT_UDBH_SHIFT)
+#define SFSTAT_UDBL_SHIFT 44
+#define SFSTAT_TL_GT_ONE (_AC(1,UL) << SFSTAT_TL_GT_ONE_SHIFT)
+#define SFSTAT_TL_GT_ONE_SHIFT 42
+#define SFSTAT_TRAP_TYPE (_AC(0x1FF,UL) << SFSTAT_TRAP_TYPE_SHIFT)
+#define SFSTAT_TRAP_TYPE_SHIFT 33
+#define SFSTAT_AFSR_MASK (_AC(0x1ffffffff,UL) << SFSTAT_AFSR_SHIFT)
+#define SFSTAT_AFSR_SHIFT 0
+
+/* ESTATE Error Enable Register, ASI=0x4b VA<63:0>=0x0 */
+#define ESTATE_ERR_CE 0x1 /* Correctable errors */
+#define ESTATE_ERR_NCE 0x2 /* TO, BERR, LDP, ETP, EDP, WP, UE, IVUE */
+#define ESTATE_ERR_ISAP 0x4 /* System address parity error */
+#define ESTATE_ERR_ALL (ESTATE_ERR_CE | \
+ ESTATE_ERR_NCE | \
+ ESTATE_ERR_ISAP)
+
+/* The various trap types that report using the above state. */
+#define TRAP_TYPE_IAE 0x09 /* Instruction Access Error */
+#define TRAP_TYPE_DAE 0x32 /* Data Access Error */
+#define TRAP_TYPE_CEE 0x63 /* Correctable ECC Error */
+
+#endif /* _SPARC64_SFAFSR_H */
diff --git a/arch/sparc/include/asm/sfp-machine.h b/arch/sparc/include/asm/sfp-machine.h
new file mode 100644
index 000000000..4a247b405
--- /dev/null
+++ b/arch/sparc/include/asm/sfp-machine.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_SFP_MACHINE_H
+#define ___ASM_SPARC_SFP_MACHINE_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/sfp-machine_64.h>
+#else
+#include <asm/sfp-machine_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/sfp-machine_32.h b/arch/sparc/include/asm/sfp-machine_32.h
new file mode 100644
index 000000000..838c9d58f
--- /dev/null
+++ b/arch/sparc/include/asm/sfp-machine_32.h
@@ -0,0 +1,212 @@
+/* Machine-dependent software floating-point definitions.
+ Sparc userland (_Q_*) version.
+ Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _SFP_MACHINE_H
+#define _SFP_MACHINE_H
+
+
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+
+/* If one NaN is signaling and the other is not,
+ * we choose that one, otherwise we choose X.
+ */
+/* For _Qp_* and _Q_*, this should prefer X, for
+ * CPU instruction emulation this should prefer Y.
+ * (see SPAMv9 B.2.2 section).
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ else \
+ { \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R,Y); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+/* Some assembly to speed things up. */
+#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
+ __asm__ ("addcc %r7,%8,%2\n\t" \
+ "addxcc %r5,%6,%1\n\t" \
+ "addx %r3,%4,%0\n" \
+ : "=r" (r2), \
+ "=&r" (r1), \
+ "=&r" (r0) \
+ : "%rJ" ((USItype)(x2)), \
+ "rI" ((USItype)(y2)), \
+ "%rJ" ((USItype)(x1)), \
+ "rI" ((USItype)(y1)), \
+ "%rJ" ((USItype)(x0)), \
+ "rI" ((USItype)(y0)) \
+ : "cc")
+
+#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
+ __asm__ ("subcc %r7,%8,%2\n\t" \
+ "subxcc %r5,%6,%1\n\t" \
+ "subx %r3,%4,%0\n" \
+ : "=r" (r2), \
+ "=&r" (r1), \
+ "=&r" (r0) \
+ : "%rJ" ((USItype)(x2)), \
+ "rI" ((USItype)(y2)), \
+ "%rJ" ((USItype)(x1)), \
+ "rI" ((USItype)(y1)), \
+ "%rJ" ((USItype)(x0)), \
+ "rI" ((USItype)(y0)) \
+ : "cc")
+
+#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
+ do { \
+ /* We need to fool gcc, as we need to pass more than 10 \
+ input/outputs. */ \
+ register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2"); \
+ __asm__ __volatile__ ( \
+ "addcc %r8,%9,%1\n\t" \
+ "addxcc %r6,%7,%0\n\t" \
+ "addxcc %r4,%5,%%g2\n\t" \
+ "addx %r2,%3,%%g1\n\t" \
+ : "=&r" (r1), \
+ "=&r" (r0) \
+ : "%rJ" ((USItype)(x3)), \
+ "rI" ((USItype)(y3)), \
+ "%rJ" ((USItype)(x2)), \
+ "rI" ((USItype)(y2)), \
+ "%rJ" ((USItype)(x1)), \
+ "rI" ((USItype)(y1)), \
+ "%rJ" ((USItype)(x0)), \
+ "rI" ((USItype)(y0)) \
+ : "cc", "g1", "g2"); \
+ __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2)); \
+ r3 = _t1; r2 = _t2; \
+ } while (0)
+
+#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
+ do { \
+ /* We need to fool gcc, as we need to pass more than 10 \
+ input/outputs. */ \
+ register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2"); \
+ __asm__ __volatile__ ( \
+ "subcc %r8,%9,%1\n\t" \
+ "subxcc %r6,%7,%0\n\t" \
+ "subxcc %r4,%5,%%g2\n\t" \
+ "subx %r2,%3,%%g1\n\t" \
+ : "=&r" (r1), \
+ "=&r" (r0) \
+ : "%rJ" ((USItype)(x3)), \
+ "rI" ((USItype)(y3)), \
+ "%rJ" ((USItype)(x2)), \
+ "rI" ((USItype)(y2)), \
+ "%rJ" ((USItype)(x1)), \
+ "rI" ((USItype)(y1)), \
+ "%rJ" ((USItype)(x0)), \
+ "rI" ((USItype)(y0)) \
+ : "cc", "g1", "g2"); \
+ __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2)); \
+ r3 = _t1; r2 = _t2; \
+ } while (0)
+
+#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) __FP_FRAC_SUB_3(x2,x1,x0,x2,x1,x0,y2,y1,y0)
+
+#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) __FP_FRAC_SUB_4(x3,x2,x1,x0,x3,x2,x1,x0,y3,y2,y1,y0)
+
+#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \
+ __asm__ ("addcc %3,%4,%3\n\t" \
+ "addxcc %2,%%g0,%2\n\t" \
+ "addxcc %1,%%g0,%1\n\t" \
+ "addx %0,%%g0,%0\n\t" \
+ : "=&r" (x3), \
+ "=&r" (x2), \
+ "=&r" (x1), \
+ "=&r" (x0) \
+ : "rI" ((USItype)(i)), \
+ "0" ((USItype)(x3)), \
+ "1" ((USItype)(x2)), \
+ "2" ((USItype)(x1)), \
+ "3" ((USItype)(x0)) \
+ : "cc")
+
+#ifndef CONFIG_SMP
+extern struct task_struct *last_task_used_math;
+#endif
+
+/* Obtain the current rounding mode. */
+#ifndef FP_ROUNDMODE
+#ifdef CONFIG_SMP
+#define FP_ROUNDMODE ((current->thread.fsr >> 30) & 0x3)
+#else
+#define FP_ROUNDMODE ((last_task_used_math->thread.fsr >> 30) & 0x3)
+#endif
+#endif
+
+/* Exception flags. */
+#define FP_EX_INVALID (1 << 4)
+#define FP_EX_OVERFLOW (1 << 3)
+#define FP_EX_UNDERFLOW (1 << 2)
+#define FP_EX_DIVZERO (1 << 1)
+#define FP_EX_INEXACT (1 << 0)
+
+#define FP_HANDLE_EXCEPTIONS return _fex
+
+#ifdef CONFIG_SMP
+#define FP_INHIBIT_RESULTS ((current->thread.fsr >> 23) & _fex)
+#else
+#define FP_INHIBIT_RESULTS ((last_task_used_math->thread.fsr >> 23) & _fex)
+#endif
+
+#ifdef CONFIG_SMP
+#define FP_TRAPPING_EXCEPTIONS ((current->thread.fsr >> 23) & 0x1f)
+#else
+#define FP_TRAPPING_EXCEPTIONS ((last_task_used_math->thread.fsr >> 23) & 0x1f)
+#endif
+
+#endif
diff --git a/arch/sparc/include/asm/sfp-machine_64.h b/arch/sparc/include/asm/sfp-machine_64.h
new file mode 100644
index 000000000..ca913ef40
--- /dev/null
+++ b/arch/sparc/include/asm/sfp-machine_64.h
@@ -0,0 +1,93 @@
+/* Machine-dependent software floating-point definitions.
+ Sparc64 kernel version.
+ Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz) and
+ David S. Miller (davem@redhat.com).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If
+ not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _SFP_MACHINE_H
+#define _SFP_MACHINE_H
+
+#define _FP_W_TYPE_SIZE 64
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+
+/* If one NaN is signaling and the other is not,
+ * we choose that one, otherwise we choose X.
+ */
+/* For _Qp_* and _Q_*, this should prefer X, for
+ * CPU instruction emulation this should prefer Y.
+ * (see SPAMv9 B.2.2 section).
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ else \
+ { \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R,Y); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+/* Obtain the current rounding mode. */
+#ifndef FP_ROUNDMODE
+#define FP_ROUNDMODE ((current_thread_info()->xfsr[0] >> 30) & 0x3)
+#endif
+
+/* Exception flags. */
+#define FP_EX_INVALID (1 << 4)
+#define FP_EX_OVERFLOW (1 << 3)
+#define FP_EX_UNDERFLOW (1 << 2)
+#define FP_EX_DIVZERO (1 << 1)
+#define FP_EX_INEXACT (1 << 0)
+
+#define FP_HANDLE_EXCEPTIONS return _fex
+
+#define FP_INHIBIT_RESULTS ((current_thread_info()->xfsr[0] >> 23) & _fex)
+
+#define FP_TRAPPING_EXCEPTIONS ((current_thread_info()->xfsr[0] >> 23) & 0x1f)
+
+#endif
diff --git a/arch/sparc/include/asm/shmparam.h b/arch/sparc/include/asm/shmparam.h
new file mode 100644
index 000000000..951a4525f
--- /dev/null
+++ b/arch/sparc/include/asm/shmparam.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_SHMPARAM_H
+#define ___ASM_SPARC_SHMPARAM_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/shmparam_64.h>
+#else
+#include <asm/shmparam_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/shmparam_32.h b/arch/sparc/include/asm/shmparam_32.h
new file mode 100644
index 000000000..9767a8b30
--- /dev/null
+++ b/arch/sparc/include/asm/shmparam_32.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASMSPARC_SHMPARAM_H
+#define _ASMSPARC_SHMPARAM_H
+
+#define __ARCH_FORCE_SHMLBA 1
+
+extern int vac_cache_size;
+#define SHMLBA (vac_cache_size ? vac_cache_size : PAGE_SIZE)
+
+#endif /* _ASMSPARC_SHMPARAM_H */
diff --git a/arch/sparc/include/asm/shmparam_64.h b/arch/sparc/include/asm/shmparam_64.h
new file mode 100644
index 000000000..c0731b571
--- /dev/null
+++ b/arch/sparc/include/asm/shmparam_64.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASMSPARC64_SHMPARAM_H
+#define _ASMSPARC64_SHMPARAM_H
+
+#include <asm/spitfire.h>
+
+#define __ARCH_FORCE_SHMLBA 1
+/* attach addr a multiple of this */
+#define SHMLBA ((PAGE_SIZE > L1DCACHE_SIZE) ? PAGE_SIZE : L1DCACHE_SIZE)
+
+#endif /* _ASMSPARC64_SHMPARAM_H */
diff --git a/arch/sparc/include/asm/sigcontext.h b/arch/sparc/include/asm/sigcontext.h
new file mode 100644
index 000000000..ee05f9d2b
--- /dev/null
+++ b/arch/sparc/include/asm/sigcontext.h
@@ -0,0 +1,109 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_SIGCONTEXT_H
+#define __SPARC_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+#include <uapi/asm/sigcontext.h>
+
+#ifndef __ASSEMBLY__
+
+#define __SUNOS_MAXWIN 31
+
+/* This is what SunOS does, so shall I unless we use new 32bit signals or rt signals. */
+struct sigcontext32 {
+ int sigc_onstack; /* state to restore */
+ int sigc_mask; /* sigmask to restore */
+ int sigc_sp; /* stack pointer */
+ int sigc_pc; /* program counter */
+ int sigc_npc; /* next program counter */
+ int sigc_psr; /* for condition codes etc */
+ int sigc_g1; /* User uses these two registers */
+ int sigc_o0; /* within the trampoline code. */
+
+ /* Now comes information regarding the users window set
+ * at the time of the signal.
+ */
+ int sigc_oswins; /* outstanding windows */
+
+ /* stack ptrs for each regwin buf */
+ unsigned int sigc_spbuf[__SUNOS_MAXWIN];
+
+ /* Windows to restore after signal */
+ struct reg_window32 sigc_wbuf[__SUNOS_MAXWIN];
+};
+
+
+/* This is what we use for 32bit new non-rt signals. */
+
+typedef struct {
+ struct {
+ unsigned int psr;
+ unsigned int pc;
+ unsigned int npc;
+ unsigned int y;
+ unsigned int u_regs[16]; /* globals and ins */
+ } si_regs;
+ int si_mask;
+} __siginfo32_t;
+
+#define __SIGC_MAXWIN 7
+
+typedef struct {
+ unsigned long locals[8];
+ unsigned long ins[8];
+} __siginfo_reg_window;
+
+typedef struct {
+ int wsaved;
+ __siginfo_reg_window reg_window[__SIGC_MAXWIN];
+ unsigned long rwbuf_stkptrs[__SIGC_MAXWIN];
+} __siginfo_rwin_t;
+
+#ifdef CONFIG_SPARC64
+typedef struct {
+ unsigned int si_float_regs [64];
+ unsigned long si_fsr;
+ unsigned long si_gsr;
+ unsigned long si_fprs;
+} __siginfo_fpu_t;
+
+/* This is what SunOS doesn't, so we have to write this alone
+ and do it properly. */
+struct sigcontext {
+ /* The size of this array has to match SI_MAX_SIZE from siginfo.h */
+ char sigc_info[128];
+ struct {
+ unsigned long u_regs[16]; /* globals and ins */
+ unsigned long tstate;
+ unsigned long tpc;
+ unsigned long tnpc;
+ unsigned int y;
+ unsigned int fprs;
+ } sigc_regs;
+ __siginfo_fpu_t * sigc_fpu_save;
+ struct {
+ void * ss_sp;
+ int ss_flags;
+ unsigned long ss_size;
+ } sigc_stack;
+ unsigned long sigc_mask;
+ __siginfo_rwin_t * sigc_rwin_save;
+};
+
+#else
+
+typedef struct {
+ unsigned long si_float_regs [32];
+ unsigned long si_fsr;
+ unsigned long si_fpqdepth;
+ struct {
+ unsigned long *insn_addr;
+ unsigned long insn;
+ } si_fpqueue [16];
+} __siginfo_fpu_t;
+#endif /* (CONFIG_SPARC64) */
+
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC_SIGCONTEXT_H) */
diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h
new file mode 100644
index 000000000..28f81081e
--- /dev/null
+++ b/arch/sparc/include/asm/signal.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_SIGNAL_H
+#define __SPARC_SIGNAL_H
+
+#ifndef __ASSEMBLY__
+#include <linux/personality.h>
+#include <linux/types.h>
+#endif
+#include <uapi/asm/signal.h>
+
+#ifndef __ASSEMBLY__
+
+#define __ARCH_HAS_KA_RESTORER
+#define __ARCH_HAS_SA_RESTORER
+
+#endif /* !(__ASSEMBLY__) */
+#endif /* !(__SPARC_SIGNAL_H) */
diff --git a/arch/sparc/include/asm/smp.h b/arch/sparc/include/asm/smp.h
new file mode 100644
index 000000000..dea59f6ce
--- /dev/null
+++ b/arch/sparc/include/asm/smp.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_SMP_H
+#define ___ASM_SPARC_SMP_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/smp_64.h>
+#else
+#include <asm/smp_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
new file mode 100644
index 000000000..2cf7971d7
--- /dev/null
+++ b/arch/sparc/include/asm/smp_32.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* smp.h: Sparc specific SMP stuff.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_SMP_H
+#define _SPARC_SMP_H
+
+#include <linux/threads.h>
+#include <asm/head.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/cpumask.h>
+
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_SMP
+
+#ifndef __ASSEMBLY__
+
+#include <asm/ptrace.h>
+#include <asm/asi.h>
+#include <linux/atomic.h>
+
+/*
+ * Private routines/data
+ */
+
+extern unsigned char boot_cpu_id;
+extern volatile unsigned long cpu_callin_map[NR_CPUS];
+extern cpumask_t smp_commenced_mask;
+extern struct linux_prom_registers smp_penguin_ctable;
+
+void cpu_panic(void);
+
+/*
+ * General functions that each host system must provide.
+ */
+
+void sun4m_init_smp(void);
+void sun4d_init_smp(void);
+
+void smp_callin(void);
+void smp_store_cpu_info(int);
+
+void smp_resched_interrupt(void);
+void smp_call_function_single_interrupt(void);
+void smp_call_function_interrupt(void);
+
+struct seq_file;
+void smp_bogo(struct seq_file *);
+void smp_info(struct seq_file *);
+
+struct sparc32_ipi_ops {
+ void (*cross_call)(void *func, cpumask_t mask, unsigned long arg1,
+ unsigned long arg2, unsigned long arg3,
+ unsigned long arg4);
+ void (*resched)(int cpu);
+ void (*single)(int cpu);
+ void (*mask_one)(int cpu);
+};
+extern const struct sparc32_ipi_ops *sparc32_ipi_ops;
+
+static inline void xc0(void *func)
+{
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask, 0, 0, 0, 0);
+}
+
+static inline void xc1(void *func, unsigned long arg1)
+{
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask, arg1, 0, 0, 0);
+}
+static inline void xc2(void *func, unsigned long arg1, unsigned long arg2)
+{
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask, arg1, arg2, 0, 0);
+}
+
+static inline void xc3(void *func, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3)
+{
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask,
+ arg1, arg2, arg3, 0);
+}
+
+static inline void xc4(void *func, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4)
+{
+ sparc32_ipi_ops->cross_call(func, *cpu_online_mask,
+ arg1, arg2, arg3, arg4);
+}
+
+void arch_send_call_function_single_ipi(int cpu);
+void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+static inline int cpu_logical_map(int cpu)
+{
+ return cpu;
+}
+
+int hard_smp_processor_id(void);
+
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+void smp_setup_cpu_possible_map(void);
+
+#endif /* !(__ASSEMBLY__) */
+
+/* Sparc specific messages. */
+#define MSG_CROSS_CALL 0x0005 /* run func on cpus */
+
+/* Empirical PROM processor mailbox constants. If the per-cpu mailbox
+ * contains something other than one of these then the ipi is from
+ * Linux's active_kernel_processor. This facility exists so that
+ * the boot monitor can capture all the other cpus when one catches
+ * a watchdog reset or the user enters the monitor using L1-A keys.
+ */
+#define MBOX_STOPCPU 0xFB
+#define MBOX_IDLECPU 0xFC
+#define MBOX_IDLECPU2 0xFD
+#define MBOX_STOPCPU2 0xFE
+
+#else /* SMP */
+
+#define hard_smp_processor_id() 0
+#define smp_setup_cpu_possible_map() do { } while (0)
+
+#endif /* !(SMP) */
+#endif /* !(_SPARC_SMP_H) */
diff --git a/arch/sparc/include/asm/smp_64.h b/arch/sparc/include/asm/smp_64.h
new file mode 100644
index 000000000..505b67008
--- /dev/null
+++ b/arch/sparc/include/asm/smp_64.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* smp.h: Sparc64 specific SMP stuff.
+ *
+ * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_SMP_H
+#define _SPARC64_SMP_H
+
+#include <linux/threads.h>
+#include <asm/asi.h>
+#include <asm/starfire.h>
+#include <asm/spitfire.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/cpumask.h>
+#include <linux/cache.h>
+
+#endif /* !(__ASSEMBLY__) */
+
+#ifdef CONFIG_SMP
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Private routines/data
+ */
+
+#include <linux/bitops.h>
+#include <linux/atomic.h>
+#include <asm/percpu.h>
+
+DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
+extern cpumask_t cpu_core_map[NR_CPUS];
+
+void smp_init_cpu_poke(void);
+void scheduler_poke(void);
+
+void arch_send_call_function_single_ipi(int cpu);
+void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+/*
+ * General functions that each host system must provide.
+ */
+
+int hard_smp_processor_id(void);
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+void smp_fill_in_cpu_possible_map(void);
+void smp_fill_in_sib_core_maps(void);
+void __noreturn cpu_play_dead(void);
+
+void smp_fetch_global_regs(void);
+void smp_fetch_global_pmu(void);
+
+struct seq_file;
+void smp_bogo(struct seq_file *);
+void smp_info(struct seq_file *);
+
+void smp_callin(void);
+void cpu_panic(void);
+void smp_synchronize_tick_client(void);
+void smp_capture(void);
+void smp_release(void);
+
+#ifdef CONFIG_HOTPLUG_CPU
+int __cpu_disable(void);
+void __cpu_die(unsigned int cpu);
+#endif
+
+#endif /* !(__ASSEMBLY__) */
+
+#else
+
+#define hard_smp_processor_id() 0
+#define smp_fill_in_sib_core_maps() do { } while (0)
+#define smp_fetch_global_regs() do { } while (0)
+#define smp_fetch_global_pmu() do { } while (0)
+#define smp_fill_in_cpu_possible_map() do { } while (0)
+#define smp_init_cpu_poke() do { } while (0)
+#define scheduler_poke() do { } while (0)
+
+#endif /* !(CONFIG_SMP) */
+
+#endif /* !(_SPARC64_SMP_H) */
diff --git a/arch/sparc/include/asm/sparsemem.h b/arch/sparc/include/asm/sparsemem.h
new file mode 100644
index 000000000..aa9a676bc
--- /dev/null
+++ b/arch/sparc/include/asm/sparsemem.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_SPARSEMEM_H
+#define _SPARC64_SPARSEMEM_H
+
+#ifdef __KERNEL__
+
+#include <asm/page.h>
+
+#define SECTION_SIZE_BITS 30
+#define MAX_PHYSMEM_BITS MAX_PHYS_ADDRESS_BITS
+
+#endif /* !(__KERNEL__) */
+
+#endif /* !(_SPARC64_SPARSEMEM_H) */
diff --git a/arch/sparc/include/asm/spinlock.h b/arch/sparc/include/asm/spinlock.h
new file mode 100644
index 000000000..3f4ce55bc
--- /dev/null
+++ b/arch/sparc/include/asm/spinlock.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_SPINLOCK_H
+#define ___ASM_SPARC_SPINLOCK_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/spinlock_64.h>
+#else
+#include <asm/spinlock_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/spinlock_32.h b/arch/sparc/include/asm/spinlock_32.h
new file mode 100644
index 000000000..bc5aa6f61
--- /dev/null
+++ b/arch/sparc/include/asm/spinlock_32.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* spinlock.h: 32-bit Sparc spinlock support.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC_SPINLOCK_H
+#define __SPARC_SPINLOCK_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/psr.h>
+#include <asm/barrier.h>
+#include <asm/processor.h> /* for cpu_relax */
+
+#define arch_spin_is_locked(lock) (*((volatile unsigned char *)(lock)) != 0)
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+ __asm__ __volatile__(
+ "\n1:\n\t"
+ "ldstub [%0], %%g2\n\t"
+ "orcc %%g2, 0x0, %%g0\n\t"
+ "bne,a 2f\n\t"
+ " ldub [%0], %%g2\n\t"
+ ".subsection 2\n"
+ "2:\n\t"
+ "orcc %%g2, 0x0, %%g0\n\t"
+ "bne,a 2b\n\t"
+ " ldub [%0], %%g2\n\t"
+ "b,a 1b\n\t"
+ ".previous\n"
+ : /* no outputs */
+ : "r" (lock)
+ : "g2", "memory", "cc");
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+ unsigned int result;
+ __asm__ __volatile__("ldstub [%1], %0"
+ : "=r" (result)
+ : "r" (lock)
+ : "memory");
+ return (result == 0);
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+ __asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
+}
+
+/* Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ *
+ * XXX This might create some problems with my dual spinlock
+ * XXX scheme, deadlocks etc. -DaveM
+ *
+ * Sort of like atomic_t's on Sparc, but even more clever.
+ *
+ * ------------------------------------
+ * | 24-bit counter | wlock | arch_rwlock_t
+ * ------------------------------------
+ * 31 8 7 0
+ *
+ * wlock signifies the one writer is in or somebody is updating
+ * counter. For a writer, if he successfully acquires the wlock,
+ * but counter is non-zero, he has to release the lock and wait,
+ * till both counter and wlock are zero.
+ *
+ * Unfortunately this scheme limits us to ~16,000,000 cpus.
+ */
+static inline void __arch_read_lock(arch_rwlock_t *rw)
+{
+ register arch_rwlock_t *lp asm("g1");
+ lp = rw;
+ __asm__ __volatile__(
+ "mov %%o7, %%g4\n\t"
+ "call ___rw_read_enter\n\t"
+ " ldstub [%%g1 + 3], %%g2\n"
+ : /* no outputs */
+ : "r" (lp)
+ : "g2", "g4", "memory", "cc");
+}
+
+#define arch_read_lock(lock) \
+do { unsigned long flags; \
+ local_irq_save(flags); \
+ __arch_read_lock(lock); \
+ local_irq_restore(flags); \
+} while(0)
+
+static inline void __arch_read_unlock(arch_rwlock_t *rw)
+{
+ register arch_rwlock_t *lp asm("g1");
+ lp = rw;
+ __asm__ __volatile__(
+ "mov %%o7, %%g4\n\t"
+ "call ___rw_read_exit\n\t"
+ " ldstub [%%g1 + 3], %%g2\n"
+ : /* no outputs */
+ : "r" (lp)
+ : "g2", "g4", "memory", "cc");
+}
+
+#define arch_read_unlock(lock) \
+do { unsigned long flags; \
+ local_irq_save(flags); \
+ __arch_read_unlock(lock); \
+ local_irq_restore(flags); \
+} while(0)
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+ register arch_rwlock_t *lp asm("g1");
+ lp = rw;
+ __asm__ __volatile__(
+ "mov %%o7, %%g4\n\t"
+ "call ___rw_write_enter\n\t"
+ " ldstub [%%g1 + 3], %%g2\n"
+ : /* no outputs */
+ : "r" (lp)
+ : "g2", "g4", "memory", "cc");
+ *(volatile __u32 *)&lp->lock = ~0U;
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *lock)
+{
+ __asm__ __volatile__(
+" st %%g0, [%0]"
+ : /* no outputs */
+ : "r" (lock)
+ : "memory");
+}
+
+static inline int arch_write_trylock(arch_rwlock_t *rw)
+{
+ unsigned int val;
+
+ __asm__ __volatile__("ldstub [%1 + 3], %0"
+ : "=r" (val)
+ : "r" (&rw->lock)
+ : "memory");
+
+ if (val == 0) {
+ val = rw->lock & ~0xff;
+ if (val)
+ ((volatile u8*)&rw->lock)[3] = 0;
+ else
+ *(volatile u32*)&rw->lock = ~0U;
+ }
+
+ return (val == 0);
+}
+
+static inline int __arch_read_trylock(arch_rwlock_t *rw)
+{
+ register arch_rwlock_t *lp asm("g1");
+ register int res asm("o0");
+ lp = rw;
+ __asm__ __volatile__(
+ "mov %%o7, %%g4\n\t"
+ "call ___rw_read_try\n\t"
+ " ldstub [%%g1 + 3], %%g2\n"
+ : "=r" (res)
+ : "r" (lp)
+ : "g2", "g4", "memory", "cc");
+ return res;
+}
+
+#define arch_read_trylock(lock) \
+({ unsigned long flags; \
+ int res; \
+ local_irq_save(flags); \
+ res = __arch_read_trylock(lock); \
+ local_irq_restore(flags); \
+ res; \
+})
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* __SPARC_SPINLOCK_H */
diff --git a/arch/sparc/include/asm/spinlock_64.h b/arch/sparc/include/asm/spinlock_64.h
new file mode 100644
index 000000000..3a9a0b0c7
--- /dev/null
+++ b/arch/sparc/include/asm/spinlock_64.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* spinlock.h: 64-bit Sparc spinlock support.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC64_SPINLOCK_H
+#define __SPARC64_SPINLOCK_H
+
+#ifndef __ASSEMBLY__
+
+#include <asm/processor.h>
+#include <asm/barrier.h>
+#include <asm/qspinlock.h>
+#include <asm/qrwlock.h>
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(__SPARC64_SPINLOCK_H) */
diff --git a/arch/sparc/include/asm/spinlock_types.h b/arch/sparc/include/asm/spinlock_types.h
new file mode 100644
index 000000000..ed1d569b6
--- /dev/null
+++ b/arch/sparc/include/asm/spinlock_types.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_SPINLOCK_TYPES_H
+#define __SPARC_SPINLOCK_TYPES_H
+
+#ifdef CONFIG_QUEUED_SPINLOCKS
+#include <asm-generic/qspinlock_types.h>
+#else
+
+typedef struct {
+ volatile unsigned char lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
+#endif /* CONFIG_QUEUED_SPINLOCKS */
+
+#ifdef CONFIG_QUEUED_RWLOCKS
+#include <asm-generic/qrwlock_types.h>
+#else
+typedef struct {
+ volatile unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED { 0 }
+#endif /* CONFIG_QUEUED_RWLOCKS */
+#endif
diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h
new file mode 100644
index 000000000..e9b7d25b2
--- /dev/null
+++ b/arch/sparc/include/asm/spitfire.h
@@ -0,0 +1,368 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_SPITFIRE_H
+#define _SPARC64_SPITFIRE_H
+
+#ifdef CONFIG_SPARC64
+
+#include <asm/asi.h>
+
+/* The following register addresses are accessible via ASI_DMMU
+ * and ASI_IMMU, that is there is a distinct and unique copy of
+ * each these registers for each TLB.
+ */
+#define TSB_TAG_TARGET 0x0000000000000000 /* All chips */
+#define TLB_SFSR 0x0000000000000018 /* All chips */
+#define TSB_REG 0x0000000000000028 /* All chips */
+#define TLB_TAG_ACCESS 0x0000000000000030 /* All chips */
+#define VIRT_WATCHPOINT 0x0000000000000038 /* All chips */
+#define PHYS_WATCHPOINT 0x0000000000000040 /* All chips */
+#define TSB_EXTENSION_P 0x0000000000000048 /* Ultra-III and later */
+#define TSB_EXTENSION_S 0x0000000000000050 /* Ultra-III and later, D-TLB only */
+#define TSB_EXTENSION_N 0x0000000000000058 /* Ultra-III and later */
+#define TLB_TAG_ACCESS_EXT 0x0000000000000060 /* Ultra-III+ and later */
+
+/* These registers only exist as one entity, and are accessed
+ * via ASI_DMMU only.
+ */
+#define PRIMARY_CONTEXT 0x0000000000000008
+#define SECONDARY_CONTEXT 0x0000000000000010
+#define DMMU_SFAR 0x0000000000000020
+#define VIRT_WATCHPOINT 0x0000000000000038
+#define PHYS_WATCHPOINT 0x0000000000000040
+
+#define SPITFIRE_HIGHEST_LOCKED_TLBENT (64 - 1)
+#define CHEETAH_HIGHEST_LOCKED_TLBENT (16 - 1)
+
+#define L1DCACHE_SIZE 0x4000
+
+#define SUN4V_CHIP_INVALID 0x00
+#define SUN4V_CHIP_NIAGARA1 0x01
+#define SUN4V_CHIP_NIAGARA2 0x02
+#define SUN4V_CHIP_NIAGARA3 0x03
+#define SUN4V_CHIP_NIAGARA4 0x04
+#define SUN4V_CHIP_NIAGARA5 0x05
+#define SUN4V_CHIP_SPARC_M6 0x06
+#define SUN4V_CHIP_SPARC_M7 0x07
+#define SUN4V_CHIP_SPARC_M8 0x08
+#define SUN4V_CHIP_SPARC64X 0x8a
+#define SUN4V_CHIP_SPARC_SN 0x8b
+#define SUN4V_CHIP_UNKNOWN 0xff
+
+/*
+ * The following CPU_ID_xxx constants are used
+ * to identify the CPU type in the setup phase
+ * (see head_64.S)
+ */
+#define CPU_ID_NIAGARA1 ('1')
+#define CPU_ID_NIAGARA2 ('2')
+#define CPU_ID_NIAGARA3 ('3')
+#define CPU_ID_NIAGARA4 ('4')
+#define CPU_ID_NIAGARA5 ('5')
+#define CPU_ID_M6 ('6')
+#define CPU_ID_M7 ('7')
+#define CPU_ID_M8 ('8')
+#define CPU_ID_SONOMA1 ('N')
+
+#ifndef __ASSEMBLY__
+
+enum ultra_tlb_layout {
+ spitfire = 0,
+ cheetah = 1,
+ cheetah_plus = 2,
+ hypervisor = 3,
+};
+
+extern enum ultra_tlb_layout tlb_type;
+
+extern int sun4v_chip_type;
+
+extern int cheetah_pcache_forced_on;
+void cheetah_enable_pcache(void);
+
+#define sparc64_highest_locked_tlbent() \
+ (tlb_type == spitfire ? \
+ SPITFIRE_HIGHEST_LOCKED_TLBENT : \
+ CHEETAH_HIGHEST_LOCKED_TLBENT)
+
+extern int num_kernel_image_mappings;
+
+/* The data cache is write through, so this just invalidates the
+ * specified line.
+ */
+static inline void spitfire_put_dcache_tag(unsigned long addr, unsigned long tag)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (tag), "r" (addr), "i" (ASI_DCACHE_TAG));
+}
+
+/* The instruction cache lines are flushed with this, but note that
+ * this does not flush the pipeline. It is possible for a line to
+ * get flushed but stale instructions to still be in the pipeline,
+ * a flush instruction (to any address) is sufficient to handle
+ * this issue after the line is invalidated.
+ */
+static inline void spitfire_put_icache_tag(unsigned long addr, unsigned long tag)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (tag), "r" (addr), "i" (ASI_IC_TAG));
+}
+
+static inline unsigned long spitfire_get_dtlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" (entry << 3), "i" (ASI_DTLB_DATA_ACCESS));
+
+ /* Clear TTE diag bits. */
+ data &= ~0x0003fe0000000000UL;
+
+ return data;
+}
+
+static inline unsigned long spitfire_get_dtlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" (entry << 3), "i" (ASI_DTLB_TAG_READ));
+ return tag;
+}
+
+static inline void spitfire_put_dtlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data), "r" (entry << 3),
+ "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static inline unsigned long spitfire_get_itlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" (entry << 3), "i" (ASI_ITLB_DATA_ACCESS));
+
+ /* Clear TTE diag bits. */
+ data &= ~0x0003fe0000000000UL;
+
+ return data;
+}
+
+static inline unsigned long spitfire_get_itlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" (entry << 3), "i" (ASI_ITLB_TAG_READ));
+ return tag;
+}
+
+static inline void spitfire_put_itlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data), "r" (entry << 3),
+ "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+static inline void spitfire_flush_dtlb_nucleus_page(unsigned long page)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (page | 0x20), "i" (ASI_DMMU_DEMAP));
+}
+
+static inline void spitfire_flush_itlb_nucleus_page(unsigned long page)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (page | 0x20), "i" (ASI_IMMU_DEMAP));
+}
+
+/* Cheetah has "all non-locked" tlb flushes. */
+static inline void cheetah_flush_dtlb_all(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x80), "i" (ASI_DMMU_DEMAP));
+}
+
+static inline void cheetah_flush_itlb_all(void)
+{
+ __asm__ __volatile__("stxa %%g0, [%0] %1\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (0x80), "i" (ASI_IMMU_DEMAP));
+}
+
+/* Cheetah has a 4-tlb layout so direct access is a bit different.
+ * The first two TLBs are fully assosciative, hold 16 entries, and are
+ * used only for locked and >8K sized translations. One exists for
+ * data accesses and one for instruction accesses.
+ *
+ * The third TLB is for data accesses to 8K non-locked translations, is
+ * 2 way assosciative, and holds 512 entries. The fourth TLB is for
+ * instruction accesses to 8K non-locked translations, is 2 way
+ * assosciative, and holds 128 entries.
+ *
+ * Cheetah has some bug where bogus data can be returned from
+ * ASI_{D,I}TLB_DATA_ACCESS loads, doing the load twice fixes
+ * the problem for me. -DaveM
+ */
+static inline unsigned long cheetah_get_ldtlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
+ "ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_DTLB_DATA_ACCESS));
+
+ return data;
+}
+
+static inline unsigned long cheetah_get_litlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
+ "ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_DATA_ACCESS));
+
+ return data;
+}
+
+static inline unsigned long cheetah_get_ldtlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_DTLB_TAG_READ));
+
+ return tag;
+}
+
+static inline unsigned long cheetah_get_litlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_TAG_READ));
+
+ return tag;
+}
+
+static inline void cheetah_put_ldtlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data),
+ "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static inline void cheetah_put_litlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data),
+ "r" ((0 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+static inline unsigned long cheetah_get_dtlb_data(int entry, int tlb)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
+ "ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_DATA_ACCESS));
+
+ return data;
+}
+
+static inline unsigned long cheetah_get_dtlb_tag(int entry, int tlb)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" ((tlb << 16) | (entry << 3)), "i" (ASI_DTLB_TAG_READ));
+ return tag;
+}
+
+static inline void cheetah_put_dtlb_data(int entry, unsigned long data, int tlb)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data),
+ "r" ((tlb << 16) | (entry << 3)),
+ "i" (ASI_DTLB_DATA_ACCESS));
+}
+
+static inline unsigned long cheetah_get_itlb_data(int entry)
+{
+ unsigned long data;
+
+ __asm__ __volatile__("ldxa [%1] %2, %%g0\n\t"
+ "ldxa [%1] %2, %0"
+ : "=r" (data)
+ : "r" ((2 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_DATA_ACCESS));
+
+ return data;
+}
+
+static inline unsigned long cheetah_get_itlb_tag(int entry)
+{
+ unsigned long tag;
+
+ __asm__ __volatile__("ldxa [%1] %2, %0"
+ : "=r" (tag)
+ : "r" ((2 << 16) | (entry << 3)), "i" (ASI_ITLB_TAG_READ));
+ return tag;
+}
+
+static inline void cheetah_put_itlb_data(int entry, unsigned long data)
+{
+ __asm__ __volatile__("stxa %0, [%1] %2\n\t"
+ "membar #Sync"
+ : /* No outputs */
+ : "r" (data), "r" ((2 << 16) | (entry << 3)),
+ "i" (ASI_ITLB_DATA_ACCESS));
+}
+
+#endif /* !(__ASSEMBLY__) */
+#endif /* CONFIG_SPARC64 */
+#endif /* !(_SPARC64_SPITFIRE_H) */
diff --git a/arch/sparc/include/asm/stacktrace.h b/arch/sparc/include/asm/stacktrace.h
new file mode 100644
index 000000000..556ec5d59
--- /dev/null
+++ b/arch/sparc/include/asm/stacktrace.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_STACKTRACE_H
+#define _SPARC64_STACKTRACE_H
+
+void stack_trace_flush(void);
+
+#endif /* _SPARC64_STACKTRACE_H */
diff --git a/arch/sparc/include/asm/starfire.h b/arch/sparc/include/asm/starfire.h
new file mode 100644
index 000000000..fb1a8c499
--- /dev/null
+++ b/arch/sparc/include/asm/starfire.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * starfire.h: Group all starfire specific code together.
+ *
+ * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
+ */
+
+#ifndef _SPARC64_STARFIRE_H
+#define _SPARC64_STARFIRE_H
+
+#ifndef __ASSEMBLY__
+
+extern int this_is_starfire;
+
+void check_if_starfire(void);
+void starfire_hookup(int);
+unsigned int starfire_translate(unsigned long imap, unsigned int upaid);
+
+#endif
+#endif
diff --git a/arch/sparc/include/asm/string.h b/arch/sparc/include/asm/string.h
new file mode 100644
index 000000000..001a17baf
--- /dev/null
+++ b/arch/sparc/include/asm/string.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_STRING_H
+#define ___ASM_SPARC_STRING_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/string_64.h>
+#else
+#include <asm/string_32.h>
+#endif
+
+/* First the mem*() things. */
+#define __HAVE_ARCH_MEMMOVE
+void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMCPY
+#define memcpy(t, f, n) __builtin_memcpy(t, f, n)
+
+#define __HAVE_ARCH_MEMSET
+#define memset(s, c, count) __builtin_memset(s, c, count)
+
+#define __HAVE_ARCH_MEMSCAN
+
+#define memscan(__arg0, __char, __arg2) \
+({ \
+ void *__memscan_zero(void *, size_t); \
+ void *__memscan_generic(void *, int, size_t); \
+ void *__retval, *__addr = (__arg0); \
+ size_t __size = (__arg2); \
+ \
+ if(__builtin_constant_p(__char) && !(__char)) \
+ __retval = __memscan_zero(__addr, __size); \
+ else \
+ __retval = __memscan_generic(__addr, (__char), __size); \
+ \
+ __retval; \
+})
+
+#define __HAVE_ARCH_MEMCMP
+int memcmp(const void *,const void *,__kernel_size_t);
+
+/* Now the str*() stuff... */
+#define __HAVE_ARCH_STRLEN
+__kernel_size_t strlen(const char *);
+
+#define __HAVE_ARCH_STRNCMP
+int strncmp(const char *, const char *, __kernel_size_t);
+
+#endif
diff --git a/arch/sparc/include/asm/string_32.h b/arch/sparc/include/asm/string_32.h
new file mode 100644
index 000000000..f488946bd
--- /dev/null
+++ b/arch/sparc/include/asm/string_32.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * string.h: External definitions for optimized assembly string
+ * routines for the Linux Kernel.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#ifndef __SPARC_STRING_H__
+#define __SPARC_STRING_H__
+
+#include <asm/page.h>
+
+#endif /* !(__SPARC_STRING_H__) */
diff --git a/arch/sparc/include/asm/string_64.h b/arch/sparc/include/asm/string_64.h
new file mode 100644
index 000000000..d5c563058
--- /dev/null
+++ b/arch/sparc/include/asm/string_64.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * string.h: External definitions for optimized assembly string
+ * routines for the Linux Kernel.
+ *
+ * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997,1999 Jakub Jelinek (jakub@redhat.com)
+ */
+
+#ifndef __SPARC64_STRING_H__
+#define __SPARC64_STRING_H__
+
+#include <asm/asi.h>
+
+#endif /* !(__SPARC64_STRING_H__) */
diff --git a/arch/sparc/include/asm/sunbpp.h b/arch/sparc/include/asm/sunbpp.h
new file mode 100644
index 000000000..55de4da70
--- /dev/null
+++ b/arch/sparc/include/asm/sunbpp.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * include/asm/sunbpp.h
+ */
+
+#ifndef _ASM_SPARC_SUNBPP_H
+#define _ASM_SPARC_SUNBPP_H
+
+struct bpp_regs {
+ /* DMA registers */
+ __volatile__ __u32 p_csr; /* DMA Control/Status Register */
+ __volatile__ __u32 p_addr; /* Address Register */
+ __volatile__ __u32 p_bcnt; /* Byte Count Register */
+ __volatile__ __u32 p_tst_csr; /* Test Control/Status (DMA2 only) */
+ /* Parallel Port registers */
+ __volatile__ __u16 p_hcr; /* Hardware Configuration Register */
+ __volatile__ __u16 p_ocr; /* Operation Configuration Register */
+ __volatile__ __u8 p_dr; /* Parallel Data Register */
+ __volatile__ __u8 p_tcr; /* Transfer Control Register */
+ __volatile__ __u8 p_or; /* Output Register */
+ __volatile__ __u8 p_ir; /* Input Register */
+ __volatile__ __u16 p_icr; /* Interrupt Control Register */
+};
+
+/* P_HCR. Time is in increments of SBus clock. */
+#define P_HCR_TEST 0x8000 /* Allows buried counters to be read */
+#define P_HCR_DSW 0x7f00 /* Data strobe width (in ticks) */
+#define P_HCR_DDS 0x007f /* Data setup before strobe (in ticks) */
+
+/* P_OCR. */
+#define P_OCR_MEM_CLR 0x8000
+#define P_OCR_DATA_SRC 0x4000 /* ) */
+#define P_OCR_DS_DSEL 0x2000 /* ) Bidirectional */
+#define P_OCR_BUSY_DSEL 0x1000 /* ) selects */
+#define P_OCR_ACK_DSEL 0x0800 /* ) */
+#define P_OCR_EN_DIAG 0x0400
+#define P_OCR_BUSY_OP 0x0200 /* Busy operation */
+#define P_OCR_ACK_OP 0x0100 /* Ack operation */
+#define P_OCR_SRST 0x0080 /* Reset state machines. Not selfcleaning. */
+#define P_OCR_IDLE 0x0008 /* PP data transfer state machine is idle */
+#define P_OCR_V_ILCK 0x0002 /* Versatec faded. Zebra only. */
+#define P_OCR_EN_VER 0x0001 /* Enable Versatec (0 - enable). Zebra only. */
+
+/* P_TCR */
+#define P_TCR_DIR 0x08
+#define P_TCR_BUSY 0x04
+#define P_TCR_ACK 0x02
+#define P_TCR_DS 0x01 /* Strobe */
+
+/* P_OR */
+#define P_OR_V3 0x20 /* ) */
+#define P_OR_V2 0x10 /* ) on Zebra only */
+#define P_OR_V1 0x08 /* ) */
+#define P_OR_INIT 0x04
+#define P_OR_AFXN 0x02 /* Auto Feed */
+#define P_OR_SLCT_IN 0x01
+
+/* P_IR */
+#define P_IR_PE 0x04
+#define P_IR_SLCT 0x02
+#define P_IR_ERR 0x01
+
+/* P_ICR */
+#define P_DS_IRQ 0x8000 /* RW1 */
+#define P_ACK_IRQ 0x4000 /* RW1 */
+#define P_BUSY_IRQ 0x2000 /* RW1 */
+#define P_PE_IRQ 0x1000 /* RW1 */
+#define P_SLCT_IRQ 0x0800 /* RW1 */
+#define P_ERR_IRQ 0x0400 /* RW1 */
+#define P_DS_IRQ_EN 0x0200 /* RW Always on rising edge */
+#define P_ACK_IRQ_EN 0x0100 /* RW Always on rising edge */
+#define P_BUSY_IRP 0x0080 /* RW 1= rising edge */
+#define P_BUSY_IRQ_EN 0x0040 /* RW */
+#define P_PE_IRP 0x0020 /* RW 1= rising edge */
+#define P_PE_IRQ_EN 0x0010 /* RW */
+#define P_SLCT_IRP 0x0008 /* RW 1= rising edge */
+#define P_SLCT_IRQ_EN 0x0004 /* RW */
+#define P_ERR_IRP 0x0002 /* RW1 1= rising edge */
+#define P_ERR_IRQ_EN 0x0001 /* RW */
+
+#endif /* !(_ASM_SPARC_SUNBPP_H) */
diff --git a/arch/sparc/include/asm/swift.h b/arch/sparc/include/asm/swift.h
new file mode 100644
index 000000000..96f6526b9
--- /dev/null
+++ b/arch/sparc/include/asm/swift.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* swift.h: Specific definitions for the _broken_ Swift SRMMU
+ * MMU module.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_SWIFT_H
+#define _SPARC_SWIFT_H
+
+/* Swift is so brain damaged, here is the mmu control register. */
+#define SWIFT_ST 0x00800000 /* SW tablewalk enable */
+#define SWIFT_WP 0x00400000 /* Watchpoint enable */
+
+/* Branch folding (buggy, disable on production systems!) */
+#define SWIFT_BF 0x00200000
+#define SWIFT_PMC 0x00180000 /* Page mode control */
+#define SWIFT_PE 0x00040000 /* Parity enable */
+#define SWIFT_PC 0x00020000 /* Parity control */
+#define SWIFT_AP 0x00010000 /* Graphics page mode control (TCX/SX) */
+#define SWIFT_AC 0x00008000 /* Alternate Cacheability (see viking.h) */
+#define SWIFT_BM 0x00004000 /* Boot mode */
+#define SWIFT_RC 0x00003c00 /* DRAM refresh control */
+#define SWIFT_IE 0x00000200 /* Instruction cache enable */
+#define SWIFT_DE 0x00000100 /* Data cache enable */
+#define SWIFT_SA 0x00000080 /* Store Allocate */
+#define SWIFT_NF 0x00000002 /* No fault mode */
+#define SWIFT_EN 0x00000001 /* MMU enable */
+
+/* Bits [13:5] select one of 512 instruction cache tags */
+static inline void swift_inv_insn_tag(unsigned long addr)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_TXTC_TAG)
+ : "memory");
+}
+
+/* Bits [12:4] select one of 512 data cache tags */
+static inline void swift_inv_data_tag(unsigned long addr)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_DATAC_TAG)
+ : "memory");
+}
+
+static inline void swift_flush_dcache(void)
+{
+ unsigned long addr;
+
+ for (addr = 0; addr < 0x2000; addr += 0x10)
+ swift_inv_data_tag(addr);
+}
+
+static inline void swift_flush_icache(void)
+{
+ unsigned long addr;
+
+ for (addr = 0; addr < 0x4000; addr += 0x20)
+ swift_inv_insn_tag(addr);
+}
+
+static inline void swift_idflash_clear(void)
+{
+ unsigned long addr;
+
+ for (addr = 0; addr < 0x2000; addr += 0x10) {
+ swift_inv_insn_tag(addr<<1);
+ swift_inv_data_tag(addr);
+ }
+}
+
+/* Swift is so broken, it isn't even safe to use the following. */
+static inline void swift_flush_page(unsigned long page)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (page), "i" (ASI_M_FLUSH_PAGE)
+ : "memory");
+}
+
+static inline void swift_flush_segment(unsigned long addr)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_FLUSH_SEG)
+ : "memory");
+}
+
+static inline void swift_flush_region(unsigned long addr)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_FLUSH_REGION)
+ : "memory");
+}
+
+static inline void swift_flush_context(void)
+{
+ __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"
+ : /* no outputs */
+ : "i" (ASI_M_FLUSH_CTX)
+ : "memory");
+}
+
+#endif /* !(_SPARC_SWIFT_H) */
diff --git a/arch/sparc/include/asm/switch_to.h b/arch/sparc/include/asm/switch_to.h
new file mode 100644
index 000000000..7cf1c5dc7
--- /dev/null
+++ b/arch/sparc/include/asm/switch_to.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_SWITCH_TO_H
+#define ___ASM_SPARC_SWITCH_TO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/switch_to_64.h>
+#else
+#include <asm/switch_to_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/switch_to_32.h b/arch/sparc/include/asm/switch_to_32.h
new file mode 100644
index 000000000..42eeafcb8
--- /dev/null
+++ b/arch/sparc/include/asm/switch_to_32.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC_SWITCH_TO_H
+#define __SPARC_SWITCH_TO_H
+
+#include <asm/smp.h>
+
+extern struct thread_info *current_set[NR_CPUS];
+
+/*
+ * Flush windows so that the VM switch which follows
+ * would not pull the stack from under us.
+ *
+ * SWITCH_ENTER and SWITCH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
+ * XXX WTF is the above comment? Found in late teen 2.4.x.
+ */
+#ifdef CONFIG_SMP
+#define SWITCH_ENTER(prv) \
+ do { \
+ if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \
+ put_psr(get_psr() | PSR_EF); \
+ fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \
+ &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \
+ clear_tsk_thread_flag(prv, TIF_USEDFPU); \
+ (prv)->thread.kregs->psr &= ~PSR_EF; \
+ } \
+ } while(0)
+
+#define SWITCH_DO_LAZY_FPU(next) /* */
+#else
+#define SWITCH_ENTER(prv) /* */
+#define SWITCH_DO_LAZY_FPU(nxt) \
+ do { \
+ if (last_task_used_math != (nxt)) \
+ (nxt)->thread.kregs->psr&=~PSR_EF; \
+ } while(0)
+#endif
+
+#define prepare_arch_switch(next) do { \
+ __asm__ __volatile__( \
+ ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
+ "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+ "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+ "save %sp, -0x40, %sp\n\t" \
+ "restore; restore; restore; restore; restore; restore; restore"); \
+} while(0)
+
+ /* Much care has gone into this code, do not touch it.
+ *
+ * We need to loadup regs l0/l1 for the newly forked child
+ * case because the trap return path relies on those registers
+ * holding certain values, gcc is told that they are clobbered.
+ * Gcc needs registers for 3 values in and 1 value out, so we
+ * clobber every non-fixed-usage register besides l2/l3/o4/o5. -DaveM
+ *
+ * Hey Dave, that do not touch sign is too much of an incentive
+ * - Anton & Pete
+ */
+#define switch_to(prev, next, last) do { \
+ SWITCH_ENTER(prev); \
+ SWITCH_DO_LAZY_FPU(next); \
+ cpumask_set_cpu(smp_processor_id(), mm_cpumask(next->active_mm)); \
+ __asm__ __volatile__( \
+ "sethi %%hi(here - 0x8), %%o7\n\t" \
+ "mov %%g6, %%g3\n\t" \
+ "or %%o7, %%lo(here - 0x8), %%o7\n\t" \
+ "rd %%psr, %%g4\n\t" \
+ "std %%sp, [%%g6 + %4]\n\t" \
+ "rd %%wim, %%g5\n\t" \
+ "wr %%g4, 0x20, %%psr\n\t" \
+ "nop\n\t" \
+ "std %%g4, [%%g6 + %3]\n\t" \
+ "ldd [%2 + %3], %%g4\n\t" \
+ "mov %2, %%g6\n\t" \
+ ".globl patchme_store_new_current\n" \
+"patchme_store_new_current:\n\t" \
+ "st %2, [%1]\n\t" \
+ "wr %%g4, 0x20, %%psr\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ "nop\n\t" /* LEON needs all 3 nops: load to %sp depends on CWP. */ \
+ "ldd [%%g6 + %4], %%sp\n\t" \
+ "wr %%g5, 0x0, %%wim\n\t" \
+ "ldd [%%sp + 0x00], %%l0\n\t" \
+ "ldd [%%sp + 0x38], %%i6\n\t" \
+ "wr %%g4, 0x0, %%psr\n\t" \
+ "nop\n\t" \
+ "nop\n\t" \
+ "jmpl %%o7 + 0x8, %%g0\n\t" \
+ " ld [%%g3 + %5], %0\n\t" \
+ "here:\n" \
+ : "=&r" (last) \
+ : "r" (&(current_set[hard_smp_processor_id()])), \
+ "r" (task_thread_info(next)), \
+ "i" (TI_KPSR), \
+ "i" (TI_KSP), \
+ "i" (TI_TASK) \
+ : "g1", "g2", "g3", "g4", "g5", "g7", \
+ "l0", "l1", "l3", "l4", "l5", "l6", "l7", \
+ "i0", "i1", "i2", "i3", "i4", "i5", \
+ "o0", "o1", "o2", "o3", "o7"); \
+ } while(0)
+
+void fpsave(unsigned long *fpregs, unsigned long *fsr,
+ void *fpqueue, unsigned long *fpqdepth);
+void synchronize_user_stack(void);
+
+#endif /* __SPARC_SWITCH_TO_H */
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
new file mode 100644
index 000000000..14f3c49bf
--- /dev/null
+++ b/arch/sparc/include/asm/switch_to_64.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __SPARC64_SWITCH_TO_64_H
+#define __SPARC64_SWITCH_TO_64_H
+
+#include <asm/visasm.h>
+
+#define prepare_arch_switch(next) \
+do { \
+ flushw_all(); \
+} while (0)
+
+ /* See what happens when you design the chip correctly?
+ *
+ * We tell gcc we clobber all non-fixed-usage registers except
+ * for l0/l1. It will use one for 'next' and the other to hold
+ * the output value of 'last'. 'next' is not referenced again
+ * past the invocation of switch_to in the scheduler, so we need
+ * not preserve it's value. Hairy, but it lets us remove 2 loads
+ * and 2 stores in this critical code path. -DaveM
+ */
+#define switch_to(prev, next, last) \
+do { save_and_clear_fpu(); \
+ __asm__ __volatile__("wr %%g0, %0, %%asi" \
+ : : "r" (ASI_AIUS)); \
+ trap_block[current_thread_info()->cpu].thread = \
+ task_thread_info(next); \
+ __asm__ __volatile__( \
+ "mov %%g4, %%g7\n\t" \
+ "stx %%i6, [%%sp + 2047 + 0x70]\n\t" \
+ "stx %%i7, [%%sp + 2047 + 0x78]\n\t" \
+ "rdpr %%wstate, %%o5\n\t" \
+ "stx %%o6, [%%g6 + %6]\n\t" \
+ "stb %%o5, [%%g6 + %5]\n\t" \
+ "rdpr %%cwp, %%o5\n\t" \
+ "stb %%o5, [%%g6 + %8]\n\t" \
+ "wrpr %%g0, 15, %%pil\n\t" \
+ "mov %4, %%g6\n\t" \
+ "ldub [%4 + %8], %%g1\n\t" \
+ "wrpr %%g1, %%cwp\n\t" \
+ "ldx [%%g6 + %6], %%o6\n\t" \
+ "ldub [%%g6 + %5], %%o5\n\t" \
+ "ldub [%%g6 + %7], %%o7\n\t" \
+ "wrpr %%o5, 0x0, %%wstate\n\t" \
+ "ldx [%%sp + 2047 + 0x70], %%i6\n\t" \
+ "ldx [%%sp + 2047 + 0x78], %%i7\n\t" \
+ "ldx [%%g6 + %9], %%g4\n\t" \
+ "wrpr %%g0, 14, %%pil\n\t" \
+ "brz,pt %%o7, switch_to_pc\n\t" \
+ " mov %%g7, %0\n\t" \
+ "sethi %%hi(ret_from_fork), %%g1\n\t" \
+ "jmpl %%g1 + %%lo(ret_from_fork), %%g0\n\t" \
+ " nop\n\t" \
+ ".globl switch_to_pc\n\t" \
+ "switch_to_pc:\n\t" \
+ : "=&r" (last), "=r" (current), "=r" (current_thread_info_reg), \
+ "=r" (__local_per_cpu_offset) \
+ : "0" (task_thread_info(next)), \
+ "i" (TI_WSTATE), "i" (TI_KSP), "i" (TI_NEW_CHILD), \
+ "i" (TI_CWP), "i" (TI_TASK) \
+ : "cc", \
+ "g1", "g2", "g3", "g7", \
+ "l1", "l2", "l3", "l4", "l5", "l6", "l7", \
+ "i0", "i1", "i2", "i3", "i4", "i5", \
+ "o0", "o1", "o2", "o3", "o4", "o5", "o7"); \
+} while(0)
+
+void synchronize_user_stack(void);
+struct pt_regs;
+void fault_in_user_windows(struct pt_regs *);
+
+#endif /* __SPARC64_SWITCH_TO_64_H */
diff --git a/arch/sparc/include/asm/syscall.h b/arch/sparc/include/asm/syscall.h
new file mode 100644
index 000000000..20c109ac8
--- /dev/null
+++ b/arch/sparc/include/asm/syscall.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_SPARC_SYSCALL_H
+#define __ASM_SPARC_SYSCALL_H
+
+#include <uapi/linux/audit.h>
+#include <linux/kernel.h>
+#include <linux/compat.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/thread_info.h>
+
+/*
+ * The syscall table always contains 32 bit pointers since we know that the
+ * address of the function to be called is (way) below 4GB. So the "int"
+ * type here is what we want [need] for both 32 bit and 64 bit systems.
+ */
+extern const unsigned int sys_call_table[];
+
+/* The system call number is given by the user in %g1 */
+static inline long syscall_get_nr(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ int syscall_p = pt_regs_is_syscall(regs);
+
+ return (syscall_p ? regs->u_regs[UREG_G1] : -1L);
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ /* XXX This needs some thought. On Sparc we don't
+ * XXX save away the original %o0 value somewhere.
+ * XXX Instead we hold it in register %l5 at the top
+ * XXX level trap frame and pass this down to the signal
+ * XXX dispatch code which is the only place that value
+ * XXX ever was needed.
+ */
+}
+
+#ifdef CONFIG_SPARC32
+static inline bool syscall_has_error(struct pt_regs *regs)
+{
+ return (regs->psr & PSR_C) ? true : false;
+}
+static inline void syscall_set_error(struct pt_regs *regs)
+{
+ regs->psr |= PSR_C;
+}
+static inline void syscall_clear_error(struct pt_regs *regs)
+{
+ regs->psr &= ~PSR_C;
+}
+#else
+static inline bool syscall_has_error(struct pt_regs *regs)
+{
+ return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false;
+}
+static inline void syscall_set_error(struct pt_regs *regs)
+{
+ regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY);
+}
+static inline void syscall_clear_error(struct pt_regs *regs)
+{
+ regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY);
+}
+#endif
+
+static inline long syscall_get_error(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ long val = regs->u_regs[UREG_I0];
+
+ return (syscall_has_error(regs) ? -val : 0);
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ long val = regs->u_regs[UREG_I0];
+
+ return val;
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+ struct pt_regs *regs,
+ int error, long val)
+{
+ if (error) {
+ syscall_set_error(regs);
+ regs->u_regs[UREG_I0] = -error;
+ } else {
+ syscall_clear_error(regs);
+ regs->u_regs[UREG_I0] = val;
+ }
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned long *args)
+{
+ int zero_extend = 0;
+ unsigned int j;
+ unsigned int n = 6;
+
+#ifdef CONFIG_SPARC64
+ if (test_tsk_thread_flag(task, TIF_32BIT))
+ zero_extend = 1;
+#endif
+
+ for (j = 0; j < n; j++) {
+ unsigned long val = regs->u_regs[UREG_I0 + j];
+
+ if (zero_extend)
+ args[j] = (u32) val;
+ else
+ args[j] = val;
+ }
+}
+
+static inline int syscall_get_arch(struct task_struct *task)
+{
+#if defined(CONFIG_SPARC64) && defined(CONFIG_COMPAT)
+ return test_tsk_thread_flag(task, TIF_32BIT)
+ ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64;
+#elif defined(CONFIG_SPARC64)
+ return AUDIT_ARCH_SPARC64;
+#else
+ return AUDIT_ARCH_SPARC;
+#endif
+}
+
+#endif /* __ASM_SPARC_SYSCALL_H */
diff --git a/arch/sparc/include/asm/syscalls.h b/arch/sparc/include/asm/syscalls.h
new file mode 100644
index 000000000..35575fbfb
--- /dev/null
+++ b/arch/sparc/include/asm/syscalls.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_SYSCALLS_H
+#define _SPARC64_SYSCALLS_H
+
+struct pt_regs;
+
+asmlinkage long sparc_fork(struct pt_regs *regs);
+asmlinkage long sparc_vfork(struct pt_regs *regs);
+asmlinkage long sparc_clone(struct pt_regs *regs);
+
+#endif /* _SPARC64_SYSCALLS_H */
diff --git a/arch/sparc/include/asm/termbits.h b/arch/sparc/include/asm/termbits.h
new file mode 100644
index 000000000..fa9de4a46
--- /dev/null
+++ b/arch/sparc/include/asm/termbits.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_TERMBITS_H
+#define _SPARC_TERMBITS_H
+
+#include <uapi/asm/termbits.h>
+
+#define VMIN 16
+#define VTIME 17
+#endif /* !(_SPARC_TERMBITS_H) */
diff --git a/arch/sparc/include/asm/thread_info.h b/arch/sparc/include/asm/thread_info.h
new file mode 100644
index 000000000..740b1743e
--- /dev/null
+++ b/arch/sparc/include/asm/thread_info.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_THREAD_INFO_H
+#define ___ASM_SPARC_THREAD_INFO_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/thread_info_64.h>
+#else
+#include <asm/thread_info_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
new file mode 100644
index 000000000..45b4955b2
--- /dev/null
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * thread_info.h: sparc low-level thread information
+ * adapted from the ppc version by Pete Zaitcev, which was
+ * adapted from the i386 version by Paul Mackerras
+ *
+ * Copyright (C) 2002 David Howells (dhowells@redhat.com)
+ * Copyright (c) 2002 Pete Zaitcev (zaitcev@yahoo.com)
+ * - Incorporating suggestions made by Linus Torvalds and Dave Miller
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <asm/ptrace.h>
+#include <asm/page.h>
+
+/*
+ * Low level task data.
+ *
+ * If you change this, change the TI_* offsets below to match.
+ */
+#define NSWINS 8
+struct thread_info {
+ unsigned long uwinmask;
+ struct task_struct *task; /* main task structure */
+ unsigned long flags; /* low level flags */
+ int cpu; /* cpu we're on */
+ int preempt_count; /* 0 => preemptable,
+ <0 => BUG */
+ int softirq_count;
+ int hardirq_count;
+
+ u32 __unused;
+
+ /* Context switch saved kernel state. */
+ unsigned long ksp; /* ... ksp __attribute__ ((aligned (8))); */
+ unsigned long kpc;
+ unsigned long kpsr;
+ unsigned long kwim;
+
+ /* A place to store user windows and stack pointers
+ * when the stack needs inspection.
+ */
+ struct reg_window32 reg_window[NSWINS]; /* align for ldd! */
+ unsigned long rwbuf_stkptrs[NSWINS];
+ unsigned long w_saved;
+};
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .uwinmask = 0, \
+ .task = &tsk, \
+ .flags = 0, \
+ .cpu = 0, \
+ .preempt_count = INIT_PREEMPT_COUNT, \
+}
+
+/* how to get the thread information struct from C */
+register struct thread_info *current_thread_info_reg asm("g6");
+#define current_thread_info() (current_thread_info_reg)
+
+/*
+ * thread information allocation
+ */
+#define THREAD_SIZE_ORDER 1
+
+#endif /* __ASSEMBLY__ */
+
+/* Size of kernel stack for each process */
+#define THREAD_SIZE (2 * PAGE_SIZE)
+
+/*
+ * Offsets in thread_info structure, used in assembly code
+ * The "#define REGWIN_SZ 0x40" was abolished, so no multiplications.
+ */
+#define TI_UWINMASK 0x00 /* uwinmask */
+#define TI_TASK 0x04
+#define TI_FLAGS 0x08
+#define TI_CPU 0x0c
+#define TI_PREEMPT 0x10 /* preempt_count */
+#define TI_SOFTIRQ 0x14 /* softirq_count */
+#define TI_HARDIRQ 0x18 /* hardirq_count */
+#define TI_KSP 0x20 /* ksp */
+#define TI_KPC 0x24 /* kpc (ldd'ed with kpc) */
+#define TI_KPSR 0x28 /* kpsr */
+#define TI_KWIM 0x2c /* kwim (ldd'ed with kpsr) */
+#define TI_REG_WINDOW 0x30
+#define TI_RWIN_SPTRS 0x230
+#define TI_W_SAVED 0x250
+
+/*
+ * thread information flag bit numbers
+ */
+#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */
+#define TIF_NOTIFY_SIGNAL 5 /* signal notifications exist */
+#define TIF_USEDFPU 8 /* FPU was used by this task
+ * this quantum (SMP) */
+#define TIF_POLLING_NRFLAG 9 /* true if poll_idle() is polling
+ * TIF_NEED_RESCHED */
+#define TIF_MEMDIE 10 /* is terminating due to OOM killer */
+
+/* as above, but as bit values */
+#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+#define _TIF_NOTIFY_SIGNAL (1<<TIF_NOTIFY_SIGNAL)
+#define _TIF_USEDFPU (1<<TIF_USEDFPU)
+#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | \
+ _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)
+
+#define is_32bit_task() (1)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
new file mode 100644
index 000000000..1a44372e2
--- /dev/null
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* thread_info.h: sparc64 low-level thread information
+ *
+ * Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef _ASM_THREAD_INFO_H
+#define _ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#define NSWINS 7
+
+#define TI_FLAG_BYTE_FAULT_CODE 0
+#define TI_FLAG_FAULT_CODE_SHIFT 56
+#define TI_FLAG_BYTE_WSTATE 1
+#define TI_FLAG_WSTATE_SHIFT 48
+#define TI_FLAG_BYTE_NOERROR 2
+#define TI_FLAG_BYTE_NOERROR_SHIFT 40
+#define TI_FLAG_BYTE_FPDEPTH 3
+#define TI_FLAG_FPDEPTH_SHIFT 32
+#define TI_FLAG_BYTE_CWP 4
+#define TI_FLAG_CWP_SHIFT 24
+#define TI_FLAG_BYTE_WSAVED 5
+#define TI_FLAG_WSAVED_SHIFT 16
+
+#include <asm/page.h>
+
+#ifndef __ASSEMBLY__
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+struct task_struct;
+
+struct thread_info {
+ /* D$ line 1 */
+ struct task_struct *task;
+ unsigned long flags;
+ __u8 fpsaved[7];
+ __u8 status;
+ unsigned long ksp;
+
+ /* D$ line 2 */
+ unsigned long fault_address;
+ struct pt_regs *kregs;
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
+ __u8 new_child;
+ __u8 __pad;
+ __u16 cpu;
+
+ unsigned long *utraps;
+
+ struct reg_window reg_window[NSWINS];
+ unsigned long rwbuf_stkptrs[NSWINS];
+
+ unsigned long gsr[7];
+ unsigned long xfsr[7];
+
+ struct pt_regs *kern_una_regs;
+ unsigned int kern_una_insn;
+
+ unsigned long fpregs[(7 * 256) / sizeof(unsigned long)]
+ __attribute__ ((aligned(64)));
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK 0x00000000
+#define TI_FLAGS 0x00000008
+#define TI_FAULT_CODE (TI_FLAGS + TI_FLAG_BYTE_FAULT_CODE)
+#define TI_WSTATE (TI_FLAGS + TI_FLAG_BYTE_WSTATE)
+#define TI_CWP (TI_FLAGS + TI_FLAG_BYTE_CWP)
+#define TI_FPDEPTH (TI_FLAGS + TI_FLAG_BYTE_FPDEPTH)
+#define TI_WSAVED (TI_FLAGS + TI_FLAG_BYTE_WSAVED)
+#define TI_SYS_NOERROR (TI_FLAGS + TI_FLAG_BYTE_NOERROR)
+#define TI_FPSAVED 0x00000010
+#define TI_KSP 0x00000018
+#define TI_FAULT_ADDR 0x00000020
+#define TI_KREGS 0x00000028
+#define TI_PRE_COUNT 0x00000030
+#define TI_NEW_CHILD 0x00000034
+#define TI_CPU 0x00000036
+#define TI_UTRAPS 0x00000038
+#define TI_REG_WINDOW 0x00000040
+#define TI_RWIN_SPTRS 0x000003c0
+#define TI_GSR 0x000003f8
+#define TI_XFSR 0x00000430
+#define TI_KUNA_REGS 0x00000468
+#define TI_KUNA_INSN 0x00000470
+#define TI_FPREGS 0x00000480
+
+/* We embed this in the uppermost byte of thread_info->flags */
+#define FAULT_CODE_WRITE 0x01 /* Write access, implies D-TLB */
+#define FAULT_CODE_DTLB 0x02 /* Miss happened in D-TLB */
+#define FAULT_CODE_ITLB 0x04 /* Miss happened in I-TLB */
+#define FAULT_CODE_WINFIXUP 0x08 /* Miss happened during spill/fill */
+#define FAULT_CODE_BLKCOMMIT 0x10 /* Use blk-commit ASI in copy_page */
+#define FAULT_CODE_BAD_RA 0x20 /* Bad RA for sun4v */
+
+#if PAGE_SHIFT == 13
+#define THREAD_SIZE (2*PAGE_SIZE)
+#define THREAD_SHIFT (PAGE_SHIFT + 1)
+#else /* PAGE_SHIFT == 13 */
+#define THREAD_SIZE PAGE_SIZE
+#define THREAD_SHIFT PAGE_SHIFT
+#endif /* PAGE_SHIFT == 13 */
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .task = &tsk, \
+ .preempt_count = INIT_PREEMPT_COUNT, \
+ .kregs = (struct pt_regs *)(init_stack+THREAD_SIZE)-1 \
+}
+
+/* how to get the thread information struct from C */
+#ifndef BUILD_VDSO
+register struct thread_info *current_thread_info_reg asm("g6");
+#define current_thread_info() (current_thread_info_reg)
+#else
+extern struct thread_info *current_thread_info(void);
+#endif
+
+/* thread information allocation */
+#if PAGE_SHIFT == 13
+#define THREAD_SIZE_ORDER 1
+#else /* PAGE_SHIFT == 13 */
+#define THREAD_SIZE_ORDER 0
+#endif /* PAGE_SHIFT == 13 */
+
+#define __thread_flag_byte_ptr(ti) \
+ ((unsigned char *)(&((ti)->flags)))
+#define __cur_thread_flag_byte_ptr __thread_flag_byte_ptr(current_thread_info())
+
+#define get_thread_fault_code() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FAULT_CODE])
+#define set_thread_fault_code(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FAULT_CODE] = (val))
+#define get_thread_wstate() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE])
+#define set_thread_wstate(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSTATE] = (val))
+#define get_thread_cwp() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP])
+#define set_thread_cwp(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_CWP] = (val))
+#define get_thread_noerror() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR])
+#define set_thread_noerror(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_NOERROR] = (val))
+#define get_thread_fpdepth() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH])
+#define set_thread_fpdepth(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_FPDEPTH] = (val))
+#define get_thread_wsaved() (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED])
+#define set_thread_wsaved(val) (__cur_thread_flag_byte_ptr[TI_FLAG_BYTE_WSAVED] = (val))
+#endif /* !(__ASSEMBLY__) */
+
+/*
+ * Thread information flags, only 16 bits are available as we encode
+ * other values into the upper 6 bytes.
+ *
+ * On trap return we need to test several values:
+ *
+ * user: need_resched, notify_resume, sigpending, wsaved
+ * kernel: fpdepth
+ *
+ * So to check for work in the kernel case we simply load the fpdepth
+ * byte out of the flags and test it. For the user case we encode the
+ * lower 3 bytes of flags as follows:
+ * ----------------------------------------
+ * | wsaved | flags byte 1 | flags byte 2 |
+ * ----------------------------------------
+ * This optimizes the user test into:
+ * ldx [%g6 + TI_FLAGS], REG1
+ * sethi %hi(_TIF_USER_WORK_MASK), REG2
+ * or REG2, %lo(_TIF_USER_WORK_MASK), REG2
+ * andcc REG1, REG2, %g0
+ * be,pt no_work_to_do
+ * nop
+ */
+#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_NOTIFY_SIGNAL 4 /* signal notifications exist */
+#define TIF_UNALIGNED 5 /* allowed to do unaligned accesses */
+#define TIF_UPROBE 6 /* breakpointed or singlestepped */
+#define TIF_32BIT 7 /* 32-bit binary */
+#define TIF_NOHZ 8 /* in adaptive nohz mode */
+#define TIF_SECCOMP 9 /* secure computing */
+#define TIF_SYSCALL_AUDIT 10 /* syscall auditing active */
+#define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */
+/* NOTE: Thread flags >= 12 should be ones we have no interest
+ * in using in assembly, else we can't use the mask as
+ * an immediate value in instructions such as andcc.
+ */
+#define TIF_MCDPER 12 /* Precise MCD exception */
+#define TIF_MEMDIE 13 /* is terminating due to OOM killer */
+#define TIF_POLLING_NRFLAG 14
+
+#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+#define _TIF_NOTIFY_SIGNAL (1<<TIF_NOTIFY_SIGNAL)
+#define _TIF_UNALIGNED (1<<TIF_UNALIGNED)
+#define _TIF_UPROBE (1<<TIF_UPROBE)
+#define _TIF_32BIT (1<<TIF_32BIT)
+#define _TIF_NOHZ (1<<TIF_NOHZ)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_USER_WORK_MASK ((0xff << TI_FLAG_WSAVED_SHIFT) | \
+ _TIF_DO_NOTIFY_RESUME_MASK | \
+ _TIF_NEED_RESCHED)
+#define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | \
+ _TIF_SIGPENDING | _TIF_UPROBE | \
+ _TIF_NOTIFY_SIGNAL)
+
+#define is_32bit_task() (test_thread_flag(TIF_32BIT))
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ *
+ * Note that there are only 8 bits available.
+ */
+
+#ifndef __ASSEMBLY__
+
+#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0)
+#define test_thread_64bit_stack(__SP) \
+ ((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \
+ false : true)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/sparc/include/asm/timer.h b/arch/sparc/include/asm/timer.h
new file mode 100644
index 000000000..eaf6195d1
--- /dev/null
+++ b/arch/sparc/include/asm/timer.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_TIMER_H
+#define ___ASM_SPARC_TIMER_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/timer_64.h>
+#else
+#include <asm/timer_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h
new file mode 100644
index 000000000..eecd26969
--- /dev/null
+++ b/arch/sparc/include/asm/timer_32.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * timer.h: Definitions for the timer chips on the Sparc.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+
+#ifndef _SPARC_TIMER_H
+#define _SPARC_TIMER_H
+
+#include <linux/clocksource.h>
+#include <linux/irqreturn.h>
+
+#include <asm-generic/percpu.h>
+
+#include <asm/cpu_type.h> /* For SUN4M_NCPUS */
+
+#define SBUS_CLOCK_RATE 2000000 /* 2MHz */
+#define TIMER_VALUE_SHIFT 9
+#define TIMER_VALUE_MASK 0x3fffff
+#define TIMER_LIMIT_BIT (1 << 31) /* Bit 31 in Counter-Timer register */
+
+/* The counter timer register has the value offset by 9 bits.
+ * From sun4m manual:
+ * When a counter reaches the value in the corresponding limit register,
+ * the Limit bit is set and the counter is set to 500 nS (i.e. 0x00000200).
+ *
+ * To compensate for this add one to the value.
+ */
+static inline unsigned int timer_value(unsigned int value)
+{
+ return (value + 1) << TIMER_VALUE_SHIFT;
+}
+
+extern volatile u32 __iomem *master_l10_counter;
+
+irqreturn_t notrace timer_interrupt(int dummy, void *dev_id);
+
+#ifdef CONFIG_SMP
+DECLARE_PER_CPU(struct clock_event_device, sparc32_clockevent);
+void register_percpu_ce(int cpu);
+#endif
+
+#endif /* !(_SPARC_TIMER_H) */
diff --git a/arch/sparc/include/asm/timer_64.h b/arch/sparc/include/asm/timer_64.h
new file mode 100644
index 000000000..ffff52c8b
--- /dev/null
+++ b/arch/sparc/include/asm/timer_64.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* timer.h: System timer definitions for sun5.
+ *
+ * Copyright (C) 1997, 2008 David S. Miller (davem@davemloft.net)
+ */
+
+#ifndef _SPARC64_TIMER_H
+#define _SPARC64_TIMER_H
+
+#include <uapi/asm/asi.h>
+#include <linux/types.h>
+#include <linux/init.h>
+
+/* The most frequently accessed fields should be first,
+ * to fit into the same cacheline.
+ */
+struct sparc64_tick_ops {
+ unsigned long ticks_per_nsec_quotient;
+ unsigned long offset;
+ unsigned long long (*get_tick)(void);
+ int (*add_compare)(unsigned long);
+ unsigned long softint_mask;
+ void (*disable_irq)(void);
+
+ void (*init_tick)(void);
+ unsigned long (*add_tick)(unsigned long);
+ unsigned long (*get_frequency)(void);
+ unsigned long frequency;
+
+ char *name;
+};
+
+extern struct sparc64_tick_ops *tick_ops;
+
+unsigned long sparc64_get_clock_tick(unsigned int cpu);
+void setup_sparc64_timer(void);
+
+#define TICK_PRIV_BIT BIT(63)
+#define TICKCMP_IRQ_BIT BIT(63)
+
+#define HBIRD_STICKCMP_ADDR 0x1fe0000f060UL
+#define HBIRD_STICK_ADDR 0x1fe0000f070UL
+
+#define GET_TICK_NINSTR 13
+struct get_tick_patch {
+ unsigned int addr;
+ unsigned int tick[GET_TICK_NINSTR];
+ unsigned int stick[GET_TICK_NINSTR];
+};
+
+extern struct get_tick_patch __get_tick_patch;
+extern struct get_tick_patch __get_tick_patch_end;
+
+static inline unsigned long get_tick(void)
+{
+ unsigned long tick, tmp1, tmp2;
+
+ __asm__ __volatile__(
+ /* read hbtick 13 instructions */
+ "661:\n"
+ " mov 0x1fe, %1\n"
+ " sllx %1, 0x20, %1\n"
+ " sethi %%hi(0xf000), %2\n"
+ " or %2, 0x70, %2\n"
+ " or %1, %2, %1\n" /* %1 = HBIRD_STICK_ADDR */
+ " add %1, 8, %2\n"
+ " ldxa [%2]%3, %0\n"
+ " ldxa [%1]%3, %1\n"
+ " ldxa [%2]%3, %2\n"
+ " sub %2, %0, %0\n" /* don't modify %xcc */
+ " brnz,pn %0, 661b\n" /* restart to save one register */
+ " sllx %2, 32, %2\n"
+ " or %2, %1, %0\n"
+ /* Common/not patched code */
+ " sllx %0, 1, %0\n"
+ " srlx %0, 1, %0\n" /* Clear TICK_PRIV_BIT */
+ /* Beginning of patch section */
+ " .section .get_tick_patch, \"ax\"\n"
+ " .word 661b\n"
+ /* read tick 2 instructions and 11 skipped */
+ " ba 1f\n"
+ " rd %%tick, %0\n"
+ " .skip 4 * (%4 - 2)\n"
+ "1:\n"
+ /* read stick 2 instructions and 11 skipped */
+ " ba 1f\n"
+ " rd %%asr24, %0\n"
+ " .skip 4 * (%4 - 2)\n"
+ "1:\n"
+ /* End of patch section */
+ " .previous\n"
+ : "=&r" (tick), "=&r" (tmp1), "=&r" (tmp2)
+ : "i" (ASI_PHYS_BYPASS_EC_E), "i" (GET_TICK_NINSTR));
+
+ return tick;
+}
+
+#endif /* _SPARC64_TIMER_H */
diff --git a/arch/sparc/include/asm/timex.h b/arch/sparc/include/asm/timex.h
new file mode 100644
index 000000000..9aac26b1f
--- /dev/null
+++ b/arch/sparc/include/asm/timex.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_TIMEX_H
+#define ___ASM_SPARC_TIMEX_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/timex_64.h>
+#else
+#include <asm/timex_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/timex_32.h b/arch/sparc/include/asm/timex_32.h
new file mode 100644
index 000000000..f86326a6f
--- /dev/null
+++ b/arch/sparc/include/asm/timex_32.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * linux/include/asm/timex.h
+ *
+ * sparc architecture timex specifications
+ */
+#ifndef _ASMsparc_TIMEX_H
+#define _ASMsparc_TIMEX_H
+
+#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
+
+#include <asm-generic/timex.h>
+
+#endif
diff --git a/arch/sparc/include/asm/timex_64.h b/arch/sparc/include/asm/timex_64.h
new file mode 100644
index 000000000..076c44f68
--- /dev/null
+++ b/arch/sparc/include/asm/timex_64.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * linux/include/asm/timex.h
+ *
+ * sparc64 architecture timex specifications
+ */
+#ifndef _ASMsparc64_TIMEX_H
+#define _ASMsparc64_TIMEX_H
+
+#include <asm/timer.h>
+
+#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
+
+/* Getting on the cycle counter on sparc64. */
+typedef unsigned long cycles_t;
+#define get_cycles() tick_ops->get_tick()
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+#endif
diff --git a/arch/sparc/include/asm/tlb.h b/arch/sparc/include/asm/tlb.h
new file mode 100644
index 000000000..7146a5772
--- /dev/null
+++ b/arch/sparc/include/asm/tlb.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_TLB_H
+#define ___ASM_SPARC_TLB_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/tlb_64.h>
+#else
+#include <asm/tlb_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/tlb_32.h b/arch/sparc/include/asm/tlb_32.h
new file mode 100644
index 000000000..5cd28a879
--- /dev/null
+++ b/arch/sparc/include/asm/tlb_32.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_TLB_H
+#define _SPARC_TLB_H
+
+#include <asm-generic/tlb.h>
+
+#endif /* _SPARC_TLB_H */
diff --git a/arch/sparc/include/asm/tlb_64.h b/arch/sparc/include/asm/tlb_64.h
new file mode 100644
index 000000000..303718748
--- /dev/null
+++ b/arch/sparc/include/asm/tlb_64.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_TLB_H
+#define _SPARC64_TLB_H
+
+#include <linux/swap.h>
+#include <linux/pagemap.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+
+#ifdef CONFIG_SMP
+void smp_flush_tlb_pending(struct mm_struct *,
+ unsigned long, unsigned long *);
+#endif
+
+#ifdef CONFIG_SMP
+void smp_flush_tlb_mm(struct mm_struct *mm);
+#define do_flush_tlb_mm(mm) smp_flush_tlb_mm(mm)
+#else
+#define do_flush_tlb_mm(mm) __flush_tlb_mm(CTX_HWBITS(mm->context), SECONDARY_CONTEXT)
+#endif
+
+void __flush_tlb_pending(unsigned long, unsigned long, unsigned long *);
+void flush_tlb_pending(void);
+
+#define tlb_flush(tlb) flush_tlb_pending()
+
+/*
+ * SPARC64's hardware TLB fill does not use the Linux page-tables
+ * and therefore we don't need a TLBI when freeing page-table pages.
+ */
+
+#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
+#define tlb_needs_table_invalidate() (false)
+#endif
+
+#include <asm-generic/tlb.h>
+
+#endif /* _SPARC64_TLB_H */
diff --git a/arch/sparc/include/asm/tlbflush.h b/arch/sparc/include/asm/tlbflush.h
new file mode 100644
index 000000000..30ae3ea21
--- /dev/null
+++ b/arch/sparc/include/asm/tlbflush.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_TLBFLUSH_H
+#define ___ASM_SPARC_TLBFLUSH_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/tlbflush_64.h>
+#else
+#include <asm/tlbflush_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/tlbflush_32.h b/arch/sparc/include/asm/tlbflush_32.h
new file mode 100644
index 000000000..470531991
--- /dev/null
+++ b/arch/sparc/include/asm/tlbflush_32.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_TLBFLUSH_H
+#define _SPARC_TLBFLUSH_H
+
+#include <asm/cachetlb_32.h>
+
+#define flush_tlb_all() \
+ sparc32_cachetlb_ops->tlb_all()
+#define flush_tlb_mm(mm) \
+ sparc32_cachetlb_ops->tlb_mm(mm)
+#define flush_tlb_range(vma, start, end) \
+ sparc32_cachetlb_ops->tlb_range(vma, start, end)
+#define flush_tlb_page(vma, addr) \
+ sparc32_cachetlb_ops->tlb_page(vma, addr)
+
+/*
+ * This is a kludge, until I know better. --zaitcev XXX
+ */
+static inline void flush_tlb_kernel_range(unsigned long start,
+ unsigned long end)
+{
+ flush_tlb_all();
+}
+
+#endif /* _SPARC_TLBFLUSH_H */
diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h
new file mode 100644
index 000000000..8b8cdaa69
--- /dev/null
+++ b/arch/sparc/include/asm/tlbflush_64.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_TLBFLUSH_H
+#define _SPARC64_TLBFLUSH_H
+
+#include <asm/mmu_context.h>
+
+/* TSB flush operations. */
+
+#define TLB_BATCH_NR 192
+
+struct tlb_batch {
+ unsigned int hugepage_shift;
+ struct mm_struct *mm;
+ unsigned long tlb_nr;
+ unsigned long active;
+ unsigned long vaddrs[TLB_BATCH_NR];
+};
+
+void flush_tsb_kernel_range(unsigned long start, unsigned long end);
+void flush_tsb_user(struct tlb_batch *tb);
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr,
+ unsigned int hugepage_shift);
+
+/* TLB flush operations. */
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long vmaddr)
+{
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+
+void flush_tlb_pending(void);
+void arch_enter_lazy_mmu_mode(void);
+void arch_leave_lazy_mmu_mode(void);
+#define arch_flush_lazy_mmu_mode() do {} while (0)
+
+/* Local cpu only. */
+void __flush_tlb_all(void);
+void __flush_tlb_page(unsigned long context, unsigned long vaddr);
+void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
+
+#ifndef CONFIG_SMP
+
+static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
+{
+ __flush_tlb_page(CTX_HWBITS(mm->context), vaddr);
+}
+
+#else /* CONFIG_SMP */
+
+void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
+void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr);
+
+#define global_flush_tlb_page(mm, vaddr) \
+ smp_flush_tlb_page(mm, vaddr)
+
+#endif /* ! CONFIG_SMP */
+
+#endif /* _SPARC64_TLBFLUSH_H */
diff --git a/arch/sparc/include/asm/topology.h b/arch/sparc/include/asm/topology.h
new file mode 100644
index 000000000..ba7b9d9d9
--- /dev/null
+++ b/arch/sparc/include/asm/topology.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_TOPOLOGY_H
+#define ___ASM_SPARC_TOPOLOGY_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/topology_64.h>
+#else
+#include <asm/topology_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/topology_32.h b/arch/sparc/include/asm/topology_32.h
new file mode 100644
index 000000000..66c4f9ff7
--- /dev/null
+++ b/arch/sparc/include/asm/topology_32.h
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC_TOPOLOGY_H
+#define _ASM_SPARC_TOPOLOGY_H
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_SPARC_TOPOLOGY_H */
diff --git a/arch/sparc/include/asm/topology_64.h b/arch/sparc/include/asm/topology_64.h
new file mode 100644
index 000000000..34c628a22
--- /dev/null
+++ b/arch/sparc/include/asm/topology_64.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_SPARC64_TOPOLOGY_H
+#define _ASM_SPARC64_TOPOLOGY_H
+
+#ifdef CONFIG_NUMA
+
+#include <asm/mmzone.h>
+
+static inline int cpu_to_node(int cpu)
+{
+ return numa_cpu_lookup_table[cpu];
+}
+
+#define cpumask_of_node(node) ((node) == -1 ? \
+ cpu_all_mask : \
+ &numa_cpumask_lookup_table[node])
+
+struct pci_bus;
+#ifdef CONFIG_PCI
+int pcibus_to_node(struct pci_bus *pbus);
+#else
+static inline int pcibus_to_node(struct pci_bus *pbus)
+{
+ return -1;
+}
+#endif
+
+#define cpumask_of_pcibus(bus) \
+ (pcibus_to_node(bus) == -1 ? \
+ cpu_all_mask : \
+ cpumask_of_node(pcibus_to_node(bus)))
+
+int __node_distance(int, int);
+#define node_distance(a, b) __node_distance(a, b)
+
+#else /* CONFIG_NUMA */
+
+#include <asm-generic/topology.h>
+
+#endif /* !(CONFIG_NUMA) */
+
+#ifdef CONFIG_SMP
+
+#include <asm/cpudata.h>
+
+#define topology_physical_package_id(cpu) (cpu_data(cpu).proc_id)
+#define topology_core_id(cpu) (cpu_data(cpu).core_id)
+#define topology_core_cpumask(cpu) (&cpu_core_sib_map[cpu])
+#define topology_core_cache_cpumask(cpu) (&cpu_core_sib_cache_map[cpu])
+#define topology_sibling_cpumask(cpu) (&per_cpu(cpu_sibling_map, cpu))
+#endif /* CONFIG_SMP */
+
+extern cpumask_t cpu_core_map[NR_CPUS];
+extern cpumask_t cpu_core_sib_map[NR_CPUS];
+extern cpumask_t cpu_core_sib_cache_map[NR_CPUS];
+
+/**
+ * Return cores that shares the last level cache.
+ */
+static inline const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+ return &cpu_core_sib_cache_map[cpu];
+}
+
+#endif /* _ASM_SPARC64_TOPOLOGY_H */
diff --git a/arch/sparc/include/asm/trap_block.h b/arch/sparc/include/asm/trap_block.h
new file mode 100644
index 000000000..ace0d48e8
--- /dev/null
+++ b/arch/sparc/include/asm/trap_block.h
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_TRAP_BLOCK_H
+#define _SPARC_TRAP_BLOCK_H
+
+#include <linux/threads.h>
+
+#include <asm/hypervisor.h>
+#include <asm/asi.h>
+
+#ifndef __ASSEMBLY__
+
+/* Trap handling code needs to get at a few critical values upon
+ * trap entry and to process TSB misses. These cannot be in the
+ * per_cpu() area as we really need to lock them into the TLB and
+ * thus make them part of the main kernel image. As a result we
+ * try to make this as small as possible.
+ *
+ * This is padded out and aligned to 64-bytes to avoid false sharing
+ * on SMP.
+ */
+
+/* If you modify the size of this structure, please update
+ * TRAP_BLOCK_SZ_SHIFT below.
+ */
+struct thread_info;
+struct trap_per_cpu {
+/* D-cache line 1: Basic thread information, cpu and device mondo queues */
+ struct thread_info *thread;
+ unsigned long pgd_paddr;
+ unsigned long cpu_mondo_pa;
+ unsigned long dev_mondo_pa;
+
+/* D-cache line 2: Error Mondo Queue and kernel buffer pointers */
+ unsigned long resum_mondo_pa;
+ unsigned long resum_kernel_buf_pa;
+ unsigned long nonresum_mondo_pa;
+ unsigned long nonresum_kernel_buf_pa;
+
+/* Dcache lines 3, 4, 5, and 6: Hypervisor Fault Status */
+ struct hv_fault_status fault_info;
+
+/* Dcache line 7: Physical addresses of CPU send mondo block and CPU list. */
+ unsigned long cpu_mondo_block_pa;
+ unsigned long cpu_list_pa;
+ unsigned long tsb_huge;
+ unsigned long tsb_huge_temp;
+
+/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size. */
+ unsigned long irq_worklist_pa;
+ unsigned int cpu_mondo_qmask;
+ unsigned int dev_mondo_qmask;
+ unsigned int resum_qmask;
+ unsigned int nonresum_qmask;
+ unsigned long __per_cpu_base;
+} __attribute__((aligned(64)));
+extern struct trap_per_cpu trap_block[NR_CPUS];
+void init_cur_cpu_trap(struct thread_info *);
+void setup_tba(void);
+extern int ncpus_probed;
+extern u64 cpu_mondo_counter[NR_CPUS];
+
+unsigned long real_hard_smp_processor_id(void);
+
+struct cpuid_patch_entry {
+ unsigned int addr;
+ unsigned int cheetah_safari[4];
+ unsigned int cheetah_jbus[4];
+ unsigned int starfire[4];
+ unsigned int sun4v[4];
+};
+extern struct cpuid_patch_entry __cpuid_patch, __cpuid_patch_end;
+
+struct sun4v_1insn_patch_entry {
+ unsigned int addr;
+ unsigned int insn;
+};
+extern struct sun4v_1insn_patch_entry __sun4v_1insn_patch,
+ __sun4v_1insn_patch_end;
+extern struct sun4v_1insn_patch_entry __fast_win_ctrl_1insn_patch,
+ __fast_win_ctrl_1insn_patch_end;
+extern struct sun4v_1insn_patch_entry __sun_m7_1insn_patch,
+ __sun_m7_1insn_patch_end;
+
+struct sun4v_2insn_patch_entry {
+ unsigned int addr;
+ unsigned int insns[2];
+};
+extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch,
+ __sun4v_2insn_patch_end;
+extern struct sun4v_2insn_patch_entry __sun_m7_2insn_patch,
+ __sun_m7_2insn_patch_end;
+
+
+#endif /* !(__ASSEMBLY__) */
+
+#define TRAP_PER_CPU_THREAD 0x00
+#define TRAP_PER_CPU_PGD_PADDR 0x08
+#define TRAP_PER_CPU_CPU_MONDO_PA 0x10
+#define TRAP_PER_CPU_DEV_MONDO_PA 0x18
+#define TRAP_PER_CPU_RESUM_MONDO_PA 0x20
+#define TRAP_PER_CPU_RESUM_KBUF_PA 0x28
+#define TRAP_PER_CPU_NONRESUM_MONDO_PA 0x30
+#define TRAP_PER_CPU_NONRESUM_KBUF_PA 0x38
+#define TRAP_PER_CPU_FAULT_INFO 0x40
+#define TRAP_PER_CPU_CPU_MONDO_BLOCK_PA 0xc0
+#define TRAP_PER_CPU_CPU_LIST_PA 0xc8
+#define TRAP_PER_CPU_TSB_HUGE 0xd0
+#define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8
+#define TRAP_PER_CPU_IRQ_WORKLIST_PA 0xe0
+#define TRAP_PER_CPU_CPU_MONDO_QMASK 0xe8
+#define TRAP_PER_CPU_DEV_MONDO_QMASK 0xec
+#define TRAP_PER_CPU_RESUM_QMASK 0xf0
+#define TRAP_PER_CPU_NONRESUM_QMASK 0xf4
+#define TRAP_PER_CPU_PER_CPU_BASE 0xf8
+
+#define TRAP_BLOCK_SZ_SHIFT 8
+
+#include <asm/scratchpad.h>
+
+#define __GET_CPUID(REG) \
+ /* Spitfire implementation (default). */ \
+661: ldxa [%g0] ASI_UPA_CONFIG, REG; \
+ srlx REG, 17, REG; \
+ and REG, 0x1f, REG; \
+ nop; \
+ .section .cpuid_patch, "ax"; \
+ /* Instruction location. */ \
+ .word 661b; \
+ /* Cheetah Safari implementation. */ \
+ ldxa [%g0] ASI_SAFARI_CONFIG, REG; \
+ srlx REG, 17, REG; \
+ and REG, 0x3ff, REG; \
+ nop; \
+ /* Cheetah JBUS implementation. */ \
+ ldxa [%g0] ASI_JBUS_CONFIG, REG; \
+ srlx REG, 17, REG; \
+ and REG, 0x1f, REG; \
+ nop; \
+ /* Starfire implementation. */ \
+ sethi %hi(0x1fff40000d0 >> 9), REG; \
+ sllx REG, 9, REG; \
+ or REG, 0xd0, REG; \
+ lduwa [REG] ASI_PHYS_BYPASS_EC_E, REG;\
+ /* sun4v implementation. */ \
+ mov SCRATCHPAD_CPUID, REG; \
+ ldxa [REG] ASI_SCRATCHPAD, REG; \
+ nop; \
+ nop; \
+ .previous;
+
+#ifdef CONFIG_SMP
+
+#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ __GET_CPUID(TMP) \
+ sethi %hi(trap_block), DEST; \
+ sllx TMP, TRAP_BLOCK_SZ_SHIFT, TMP; \
+ or DEST, %lo(trap_block), DEST; \
+ add DEST, TMP, DEST; \
+
+/* Clobbers TMP, current address space PGD phys address into DEST. */
+#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
+
+/* Clobbers TMP, loads local processor's IRQ work area into DEST. */
+#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
+
+/* Clobbers TMP, loads DEST with current thread info pointer. */
+#define TRAP_LOAD_THREAD_REG(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
+
+/* Given the current thread info pointer in THR, load the per-cpu
+ * area base of the current processor into DEST. REG1, REG2, and REG3 are
+ * clobbered.
+ *
+ * You absolutely cannot use DEST as a temporary in this code. The
+ * reason is that traps can happen during execution, and return from
+ * trap will load the fully resolved DEST per-cpu base. This can corrupt
+ * the calculations done by the macro mid-stream.
+ */
+#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3) \
+ lduh [THR + TI_CPU], REG1; \
+ sethi %hi(trap_block), REG2; \
+ sllx REG1, TRAP_BLOCK_SZ_SHIFT, REG1; \
+ or REG2, %lo(trap_block), REG2; \
+ add REG2, REG1, REG2; \
+ ldx [REG2 + TRAP_PER_CPU_PER_CPU_BASE], DEST;
+
+#else
+
+#define TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ sethi %hi(trap_block), DEST; \
+ or DEST, %lo(trap_block), DEST; \
+
+/* Uniprocessor versions, we know the cpuid is zero. */
+#define TRAP_LOAD_PGD_PHYS(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
+
+/* Clobbers TMP, loads local processor's IRQ work area into DEST. */
+#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST;
+
+#define TRAP_LOAD_THREAD_REG(DEST, TMP) \
+ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \
+ ldx [DEST + TRAP_PER_CPU_THREAD], DEST;
+
+/* No per-cpu areas on uniprocessor, so no need to load DEST. */
+#define LOAD_PER_CPU_BASE(DEST, THR, REG1, REG2, REG3)
+
+#endif /* !(CONFIG_SMP) */
+
+#endif /* _SPARC_TRAP_BLOCK_H */
diff --git a/arch/sparc/include/asm/traps.h b/arch/sparc/include/asm/traps.h
new file mode 100644
index 000000000..2fba2602b
--- /dev/null
+++ b/arch/sparc/include/asm/traps.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * traps.h: Format of entries for the Sparc trap table.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_TRAPS_H
+#define _SPARC_TRAPS_H
+
+#include <uapi/asm/traps.h>
+
+#ifndef __ASSEMBLY__
+/* This is for V8 compliant Sparc CPUS */
+struct tt_entry {
+ unsigned long inst_one;
+ unsigned long inst_two;
+ unsigned long inst_three;
+ unsigned long inst_four;
+};
+
+/* We set this to _start in system setup. */
+extern struct tt_entry *sparc_ttable;
+
+#endif /* !(__ASSEMBLY__) */
+#endif /* !(_SPARC_TRAPS_H) */
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
new file mode 100644
index 000000000..522a677e0
--- /dev/null
+++ b/arch/sparc/include/asm/tsb.h
@@ -0,0 +1,380 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_TSB_H
+#define _SPARC64_TSB_H
+
+/* The sparc64 TSB is similar to the powerpc hashtables. It's a
+ * power-of-2 sized table of TAG/PTE pairs. The cpu precomputes
+ * pointers into this table for 8K and 64K page sizes, and also a
+ * comparison TAG based upon the virtual address and context which
+ * faults.
+ *
+ * TLB miss trap handler software does the actual lookup via something
+ * of the form:
+ *
+ * ldxa [%g0] ASI_{D,I}MMU_TSB_8KB_PTR, %g1
+ * ldxa [%g0] ASI_{D,I}MMU, %g6
+ * sllx %g6, 22, %g6
+ * srlx %g6, 22, %g6
+ * ldda [%g1] ASI_NUCLEUS_QUAD_LDD, %g4
+ * cmp %g4, %g6
+ * bne,pn %xcc, tsb_miss_{d,i}tlb
+ * mov FAULT_CODE_{D,I}TLB, %g3
+ * stxa %g5, [%g0] ASI_{D,I}TLB_DATA_IN
+ * retry
+ *
+ *
+ * Each 16-byte slot of the TSB is the 8-byte tag and then the 8-byte
+ * PTE. The TAG is of the same layout as the TLB TAG TARGET mmu
+ * register which is:
+ *
+ * -------------------------------------------------
+ * | - | CONTEXT | - | VADDR bits 63:22 |
+ * -------------------------------------------------
+ * 63 61 60 48 47 42 41 0
+ *
+ * But actually, since we use per-mm TSB's, we zero out the CONTEXT
+ * field.
+ *
+ * Like the powerpc hashtables we need to use locking in order to
+ * synchronize while we update the entries. PTE updates need locking
+ * as well.
+ *
+ * We need to carefully choose a lock bits for the TSB entry. We
+ * choose to use bit 47 in the tag. Also, since we never map anything
+ * at page zero in context zero, we use zero as an invalid tag entry.
+ * When the lock bit is set, this forces a tag comparison failure.
+ */
+
+#define TSB_TAG_LOCK_BIT 47
+#define TSB_TAG_LOCK_HIGH (1 << (TSB_TAG_LOCK_BIT - 32))
+
+#define TSB_TAG_INVALID_BIT 46
+#define TSB_TAG_INVALID_HIGH (1 << (TSB_TAG_INVALID_BIT - 32))
+
+/* Some cpus support physical address quad loads. We want to use
+ * those if possible so we don't need to hard-lock the TSB mapping
+ * into the TLB. We encode some instruction patching in order to
+ * support this.
+ *
+ * The kernel TSB is locked into the TLB by virtue of being in the
+ * kernel image, so we don't play these games for swapper_tsb access.
+ */
+#ifndef __ASSEMBLY__
+struct tsb_ldquad_phys_patch_entry {
+ unsigned int addr;
+ unsigned int sun4u_insn;
+ unsigned int sun4v_insn;
+};
+extern struct tsb_ldquad_phys_patch_entry __tsb_ldquad_phys_patch,
+ __tsb_ldquad_phys_patch_end;
+
+struct tsb_phys_patch_entry {
+ unsigned int addr;
+ unsigned int insn;
+};
+extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
+#endif
+#define TSB_LOAD_QUAD(TSB, REG) \
+661: ldda [TSB] ASI_NUCLEUS_QUAD_LDD, REG; \
+ .section .tsb_ldquad_phys_patch, "ax"; \
+ .word 661b; \
+ ldda [TSB] ASI_QUAD_LDD_PHYS, REG; \
+ ldda [TSB] ASI_QUAD_LDD_PHYS_4V, REG; \
+ .previous
+
+#define TSB_LOAD_TAG_HIGH(TSB, REG) \
+661: lduwa [TSB] ASI_N, REG; \
+ .section .tsb_phys_patch, "ax"; \
+ .word 661b; \
+ lduwa [TSB] ASI_PHYS_USE_EC, REG; \
+ .previous
+
+#define TSB_LOAD_TAG(TSB, REG) \
+661: ldxa [TSB] ASI_N, REG; \
+ .section .tsb_phys_patch, "ax"; \
+ .word 661b; \
+ ldxa [TSB] ASI_PHYS_USE_EC, REG; \
+ .previous
+
+#define TSB_CAS_TAG_HIGH(TSB, REG1, REG2) \
+661: casa [TSB] ASI_N, REG1, REG2; \
+ .section .tsb_phys_patch, "ax"; \
+ .word 661b; \
+ casa [TSB] ASI_PHYS_USE_EC, REG1, REG2; \
+ .previous
+
+#define TSB_CAS_TAG(TSB, REG1, REG2) \
+661: casxa [TSB] ASI_N, REG1, REG2; \
+ .section .tsb_phys_patch, "ax"; \
+ .word 661b; \
+ casxa [TSB] ASI_PHYS_USE_EC, REG1, REG2; \
+ .previous
+
+#define TSB_STORE(ADDR, VAL) \
+661: stxa VAL, [ADDR] ASI_N; \
+ .section .tsb_phys_patch, "ax"; \
+ .word 661b; \
+ stxa VAL, [ADDR] ASI_PHYS_USE_EC; \
+ .previous
+
+#define TSB_LOCK_TAG(TSB, REG1, REG2) \
+99: TSB_LOAD_TAG_HIGH(TSB, REG1); \
+ sethi %hi(TSB_TAG_LOCK_HIGH), REG2;\
+ andcc REG1, REG2, %g0; \
+ bne,pn %icc, 99b; \
+ nop; \
+ TSB_CAS_TAG_HIGH(TSB, REG1, REG2); \
+ cmp REG1, REG2; \
+ bne,pn %icc, 99b; \
+ nop; \
+
+#define TSB_WRITE(TSB, TTE, TAG) \
+ add TSB, 0x8, TSB; \
+ TSB_STORE(TSB, TTE); \
+ sub TSB, 0x8, TSB; \
+ TSB_STORE(TSB, TAG);
+
+ /* Do a kernel page table walk. Leaves valid PTE value in
+ * REG1. Jumps to FAIL_LABEL on early page table walk
+ * termination. VADDR will not be clobbered, but REG2 will.
+ *
+ * There are two masks we must apply to propagate bits from
+ * the virtual address into the PTE physical address field
+ * when dealing with huge pages. This is because the page
+ * table boundaries do not match the huge page size(s) the
+ * hardware supports.
+ *
+ * In these cases we propagate the bits that are below the
+ * page table level where we saw the huge page mapping, but
+ * are still within the relevant physical bits for the huge
+ * page size in question. So for PMD mappings (which fall on
+ * bit 23, for 8MB per PMD) we must propagate bit 22 for a
+ * 4MB huge page. For huge PUDs (which fall on bit 33, for
+ * 8GB per PUD), we have to accommodate 256MB and 2GB huge
+ * pages. So for those we propagate bits 32 to 28.
+ */
+#define KERN_PGTABLE_WALK(VADDR, REG1, REG2, FAIL_LABEL) \
+ sethi %hi(swapper_pg_dir), REG1; \
+ or REG1, %lo(swapper_pg_dir), REG1; \
+ sllx VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
+ srlx REG2, 64 - PAGE_SHIFT, REG2; \
+ andn REG2, 0x7, REG2; \
+ ldx [REG1 + REG2], REG1; \
+ brz,pn REG1, FAIL_LABEL; \
+ sllx VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \
+ srlx REG2, 64 - PAGE_SHIFT, REG2; \
+ andn REG2, 0x7, REG2; \
+ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+ brz,pn REG1, FAIL_LABEL; \
+ sethi %uhi(_PAGE_PUD_HUGE), REG2; \
+ brz,pn REG1, FAIL_LABEL; \
+ sllx REG2, 32, REG2; \
+ andcc REG1, REG2, %g0; \
+ sethi %hi(0xf8000000), REG2; \
+ bne,pt %xcc, 697f; \
+ sllx REG2, 1, REG2; \
+ sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
+ srlx REG2, 64 - PAGE_SHIFT, REG2; \
+ andn REG2, 0x7, REG2; \
+ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+ sethi %uhi(_PAGE_PMD_HUGE), REG2; \
+ brz,pn REG1, FAIL_LABEL; \
+ sllx REG2, 32, REG2; \
+ andcc REG1, REG2, %g0; \
+ be,pn %xcc, 698f; \
+ sethi %hi(0x400000), REG2; \
+697: brgez,pn REG1, FAIL_LABEL; \
+ andn REG1, REG2, REG1; \
+ and VADDR, REG2, REG2; \
+ ba,pt %xcc, 699f; \
+ or REG1, REG2, REG1; \
+698: sllx VADDR, 64 - PMD_SHIFT, REG2; \
+ srlx REG2, 64 - PAGE_SHIFT, REG2; \
+ andn REG2, 0x7, REG2; \
+ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+ brgez,pn REG1, FAIL_LABEL; \
+ nop; \
+699:
+
+ /* PUD has been loaded into REG1, interpret the value, seeing
+ * if it is a HUGE PUD or a normal one. If it is not valid
+ * then jump to FAIL_LABEL. If it is a HUGE PUD, and it
+ * translates to a valid PTE, branch to PTE_LABEL.
+ *
+ * We have to propagate bits [32:22] from the virtual address
+ * to resolve at 4M granularity.
+ */
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+#define USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
+700: ba 700f; \
+ nop; \
+ .section .pud_huge_patch, "ax"; \
+ .word 700b; \
+ nop; \
+ .previous; \
+ brz,pn REG1, FAIL_LABEL; \
+ sethi %uhi(_PAGE_PUD_HUGE), REG2; \
+ sllx REG2, 32, REG2; \
+ andcc REG1, REG2, %g0; \
+ be,pt %xcc, 700f; \
+ sethi %hi(0xffe00000), REG2; \
+ sllx REG2, 1, REG2; \
+ brgez,pn REG1, FAIL_LABEL; \
+ andn REG1, REG2, REG1; \
+ and VADDR, REG2, REG2; \
+ brlz,pt REG1, PTE_LABEL; \
+ or REG1, REG2, REG1; \
+700:
+#else
+#define USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
+ brz,pn REG1, FAIL_LABEL; \
+ nop;
+#endif
+
+ /* PMD has been loaded into REG1, interpret the value, seeing
+ * if it is a HUGE PMD or a normal one. If it is not valid
+ * then jump to FAIL_LABEL. If it is a HUGE PMD, and it
+ * translates to a valid PTE, branch to PTE_LABEL.
+ *
+ * We have to propagate the 4MB bit of the virtual address
+ * because we are fabricating 8MB pages using 4MB hw pages.
+ */
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+#define USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
+ brz,pn REG1, FAIL_LABEL; \
+ sethi %uhi(_PAGE_PMD_HUGE), REG2; \
+ sllx REG2, 32, REG2; \
+ andcc REG1, REG2, %g0; \
+ be,pt %xcc, 700f; \
+ sethi %hi(4 * 1024 * 1024), REG2; \
+ brgez,pn REG1, FAIL_LABEL; \
+ andn REG1, REG2, REG1; \
+ and VADDR, REG2, REG2; \
+ brlz,pt REG1, PTE_LABEL; \
+ or REG1, REG2, REG1; \
+700:
+#else
+#define USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, PTE_LABEL) \
+ brz,pn REG1, FAIL_LABEL; \
+ nop;
+#endif
+
+ /* Do a user page table walk in MMU globals. Leaves final,
+ * valid, PTE value in REG1. Jumps to FAIL_LABEL on early
+ * page table walk termination or if the PTE is not valid.
+ *
+ * Physical base of page tables is in PHYS_PGD which will not
+ * be modified.
+ *
+ * VADDR will not be clobbered, but REG1 and REG2 will.
+ */
+#define USER_PGTABLE_WALK_TL1(VADDR, PHYS_PGD, REG1, REG2, FAIL_LABEL) \
+ sllx VADDR, 64 - (PGDIR_SHIFT + PGDIR_BITS), REG2; \
+ srlx REG2, 64 - PAGE_SHIFT, REG2; \
+ andn REG2, 0x7, REG2; \
+ ldxa [PHYS_PGD + REG2] ASI_PHYS_USE_EC, REG1; \
+ brz,pn REG1, FAIL_LABEL; \
+ sllx VADDR, 64 - (PUD_SHIFT + PUD_BITS), REG2; \
+ srlx REG2, 64 - PAGE_SHIFT, REG2; \
+ andn REG2, 0x7, REG2; \
+ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+ USER_PGTABLE_CHECK_PUD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \
+ brz,pn REG1, FAIL_LABEL; \
+ sllx VADDR, 64 - (PMD_SHIFT + PMD_BITS), REG2; \
+ srlx REG2, 64 - PAGE_SHIFT, REG2; \
+ andn REG2, 0x7, REG2; \
+ ldxa [REG1 + REG2] ASI_PHYS_USE_EC, REG1; \
+ USER_PGTABLE_CHECK_PMD_HUGE(VADDR, REG1, REG2, FAIL_LABEL, 800f) \
+ sllx VADDR, 64 - PMD_SHIFT, REG2; \
+ srlx REG2, 64 - PAGE_SHIFT, REG2; \
+ andn REG2, 0x7, REG2; \
+ add REG1, REG2, REG1; \
+ ldxa [REG1] ASI_PHYS_USE_EC, REG1; \
+ brgez,pn REG1, FAIL_LABEL; \
+ nop; \
+800:
+
+/* Lookup a OBP mapping on VADDR in the prom_trans[] table at TL>0.
+ * If no entry is found, FAIL_LABEL will be branched to. On success
+ * the resulting PTE value will be left in REG1. VADDR is preserved
+ * by this routine.
+ */
+#define OBP_TRANS_LOOKUP(VADDR, REG1, REG2, REG3, FAIL_LABEL) \
+ sethi %hi(prom_trans), REG1; \
+ or REG1, %lo(prom_trans), REG1; \
+97: ldx [REG1 + 0x00], REG2; \
+ brz,pn REG2, FAIL_LABEL; \
+ nop; \
+ ldx [REG1 + 0x08], REG3; \
+ add REG2, REG3, REG3; \
+ cmp REG2, VADDR; \
+ bgu,pt %xcc, 98f; \
+ cmp VADDR, REG3; \
+ bgeu,pt %xcc, 98f; \
+ ldx [REG1 + 0x10], REG3; \
+ sub VADDR, REG2, REG2; \
+ ba,pt %xcc, 99f; \
+ add REG3, REG2, REG1; \
+98: ba,pt %xcc, 97b; \
+ add REG1, (3 * 8), REG1; \
+99:
+
+ /* We use a 32K TSB for the whole kernel, this allows to
+ * handle about 16MB of modules and vmalloc mappings without
+ * incurring many hash conflicts.
+ */
+#define KERNEL_TSB_SIZE_BYTES (32 * 1024)
+#define KERNEL_TSB_NENTRIES \
+ (KERNEL_TSB_SIZE_BYTES / 16)
+#define KERNEL_TSB4M_NENTRIES 4096
+
+ /* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
+ * on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries
+ * and the found TTE will be left in REG1. REG3 and REG4 must
+ * be an even/odd pair of registers.
+ *
+ * VADDR and TAG will be preserved and not clobbered by this macro.
+ */
+#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
+661: sethi %uhi(swapper_tsb), REG1; \
+ sethi %hi(swapper_tsb), REG2; \
+ or REG1, %ulo(swapper_tsb), REG1; \
+ or REG2, %lo(swapper_tsb), REG2; \
+ .section .swapper_tsb_phys_patch, "ax"; \
+ .word 661b; \
+ .previous; \
+ sllx REG1, 32, REG1; \
+ or REG1, REG2, REG1; \
+ srlx VADDR, PAGE_SHIFT, REG2; \
+ and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
+ sllx REG2, 4, REG2; \
+ add REG1, REG2, REG2; \
+ TSB_LOAD_QUAD(REG2, REG3); \
+ cmp REG3, TAG; \
+ be,a,pt %xcc, OK_LABEL; \
+ mov REG4, REG1;
+
+#ifndef CONFIG_DEBUG_PAGEALLOC
+ /* This version uses a trick, the TAG is already (VADDR >> 22) so
+ * we can make use of that for the index computation.
+ */
+#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
+661: sethi %uhi(swapper_4m_tsb), REG1; \
+ sethi %hi(swapper_4m_tsb), REG2; \
+ or REG1, %ulo(swapper_4m_tsb), REG1; \
+ or REG2, %lo(swapper_4m_tsb), REG2; \
+ .section .swapper_4m_tsb_phys_patch, "ax"; \
+ .word 661b; \
+ .previous; \
+ sllx REG1, 32, REG1; \
+ or REG1, REG2, REG1; \
+ and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
+ sllx REG2, 4, REG2; \
+ add REG1, REG2, REG2; \
+ TSB_LOAD_QUAD(REG2, REG3); \
+ cmp REG3, TAG; \
+ be,a,pt %xcc, OK_LABEL; \
+ mov REG4, REG1;
+#endif
+
+#endif /* !(_SPARC64_TSB_H) */
diff --git a/arch/sparc/include/asm/tsunami.h b/arch/sparc/include/asm/tsunami.h
new file mode 100644
index 000000000..acaf014ef
--- /dev/null
+++ b/arch/sparc/include/asm/tsunami.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * tsunami.h: Module specific definitions for Tsunami V8 Sparcs
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_TSUNAMI_H
+#define _SPARC_TSUNAMI_H
+
+#include <asm/asi.h>
+
+/* The MMU control register on the Tsunami:
+ *
+ * -----------------------------------------------------------------------
+ * | implvers |SW|AV|DV|MV| RSV |PC|ITD|ALC| RSV |PE| RC |IE|DE|RSV|NF|ME|
+ * -----------------------------------------------------------------------
+ * 31 24 23 22 21 20 19-18 17 16 14 13-12 11 10-9 8 7 6-2 1 0
+ *
+ * SW: Enable Software Table Walks 0=off 1=on
+ * AV: Address View bit
+ * DV: Data View bit
+ * MV: Memory View bit
+ * PC: Parity Control
+ * ITD: ITBR disable
+ * ALC: Alternate Cacheable
+ * PE: Parity Enable 0=off 1=on
+ * RC: Refresh Control
+ * IE: Instruction cache Enable 0=off 1=on
+ * DE: Data cache Enable 0=off 1=on
+ * NF: No Fault, same as all other SRMMUs
+ * ME: MMU Enable, same as all other SRMMUs
+ */
+
+#define TSUNAMI_SW 0x00800000
+#define TSUNAMI_AV 0x00400000
+#define TSUNAMI_DV 0x00200000
+#define TSUNAMI_MV 0x00100000
+#define TSUNAMI_PC 0x00020000
+#define TSUNAMI_ITD 0x00010000
+#define TSUNAMI_ALC 0x00008000
+#define TSUNAMI_PE 0x00001000
+#define TSUNAMI_RCMASK 0x00000C00
+#define TSUNAMI_IENAB 0x00000200
+#define TSUNAMI_DENAB 0x00000100
+#define TSUNAMI_NF 0x00000002
+#define TSUNAMI_ME 0x00000001
+
+static inline void tsunami_flush_icache(void)
+{
+ __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"
+ : /* no outputs */
+ : "i" (ASI_M_IC_FLCLEAR)
+ : "memory");
+}
+
+static inline void tsunami_flush_dcache(void)
+{
+ __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"
+ : /* no outputs */
+ : "i" (ASI_M_DC_FLCLEAR)
+ : "memory");
+}
+
+#endif /* !(_SPARC_TSUNAMI_H) */
diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h
new file mode 100644
index 000000000..8f6469408
--- /dev/null
+++ b/arch/sparc/include/asm/ttable.h
@@ -0,0 +1,694 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_TTABLE_H
+#define _SPARC64_TTABLE_H
+
+#include <asm/utrap.h>
+#include <asm/pil.h>
+
+#ifdef __ASSEMBLY__
+#include <asm/thread_info.h>
+#endif
+
+#define BOOT_KERNEL b sparc64_boot; nop; nop; nop; nop; nop; nop; nop;
+
+/* We need a "cleaned" instruction... */
+#define CLEAN_WINDOW \
+ rdpr %cleanwin, %l0; add %l0, 1, %l0; \
+ wrpr %l0, 0x0, %cleanwin; \
+ clr %o0; clr %o1; clr %o2; clr %o3; \
+ clr %o4; clr %o5; clr %o6; clr %o7; \
+ clr %l0; clr %l1; clr %l2; clr %l3; \
+ clr %l4; clr %l5; clr %l6; clr %l7; \
+ retry; \
+ nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
+
+#define TRAP(routine) \
+ sethi %hi(109f), %g7; \
+ ba,pt %xcc, etrap; \
+109: or %g7, %lo(109b), %g7; \
+ call routine; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,pt %xcc, rtrap; \
+ nop; \
+ nop;
+
+#define TRAP_7INSNS(routine) \
+ sethi %hi(109f), %g7; \
+ ba,pt %xcc, etrap; \
+109: or %g7, %lo(109b), %g7; \
+ call routine; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,pt %xcc, rtrap; \
+ nop;
+
+#define TRAP_SAVEFPU(routine) \
+ sethi %hi(109f), %g7; \
+ ba,pt %xcc, do_fptrap; \
+109: or %g7, %lo(109b), %g7; \
+ call routine; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,pt %xcc, rtrap; \
+ nop; \
+ nop;
+
+#define TRAP_NOSAVE(routine) \
+ ba,pt %xcc, routine; \
+ nop; \
+ nop; nop; nop; nop; nop; nop;
+
+#define TRAP_NOSAVE_7INSNS(routine) \
+ ba,pt %xcc, routine; \
+ nop; \
+ nop; nop; nop; nop; nop;
+
+#define TRAPTL1(routine) \
+ sethi %hi(109f), %g7; \
+ ba,pt %xcc, etraptl1; \
+109: or %g7, %lo(109b), %g7; \
+ call routine; \
+ add %sp, PTREGS_OFF, %o0; \
+ ba,pt %xcc, rtrap; \
+ nop; \
+ nop;
+
+#define TRAP_ARG(routine, arg) \
+ sethi %hi(109f), %g7; \
+ ba,pt %xcc, etrap; \
+109: or %g7, %lo(109b), %g7; \
+ add %sp, PTREGS_OFF, %o0; \
+ call routine; \
+ mov arg, %o1; \
+ ba,pt %xcc, rtrap; \
+ nop;
+
+#define TRAPTL1_ARG(routine, arg) \
+ sethi %hi(109f), %g7; \
+ ba,pt %xcc, etraptl1; \
+109: or %g7, %lo(109b), %g7; \
+ add %sp, PTREGS_OFF, %o0; \
+ call routine; \
+ mov arg, %o1; \
+ ba,pt %xcc, rtrap; \
+ nop;
+
+#define SYSCALL_TRAP(routine, systbl) \
+ rdpr %pil, %g2; \
+ mov TSTATE_SYSCALL, %g3; \
+ sethi %hi(109f), %g7; \
+ ba,pt %xcc, etrap_syscall; \
+109: or %g7, %lo(109b), %g7; \
+ sethi %hi(systbl), %l7; \
+ ba,pt %xcc, routine; \
+ or %l7, %lo(systbl), %l7;
+
+#define TRAP_UTRAP(handler,lvl) \
+ mov handler, %g3; \
+ ba,pt %xcc, utrap_trap; \
+ mov lvl, %g4; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ nop;
+
+#ifdef CONFIG_COMPAT
+#define LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sys_call_table32)
+#else
+#define LINUX_32BIT_SYSCALL_TRAP BTRAP(0x110)
+#endif
+#define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64)
+#define GETCC_TRAP TRAP(getcc)
+#define SETCC_TRAP TRAP(setcc)
+#define BREAKPOINT_TRAP TRAP(breakpoint_trap)
+
+#ifdef CONFIG_TRACE_IRQFLAGS
+
+#define TRAP_IRQ(routine, level) \
+ rdpr %pil, %g2; \
+ wrpr %g0, PIL_NORMAL_MAX, %pil; \
+ sethi %hi(1f-4), %g7; \
+ ba,pt %xcc, etrap_irq; \
+ or %g7, %lo(1f-4), %g7; \
+ nop; \
+ nop; \
+ nop; \
+ .subsection 2; \
+1: call trace_hardirqs_off; \
+ nop; \
+ mov level, %o0; \
+ call routine; \
+ add %sp, PTREGS_OFF, %o1; \
+ ba,a,pt %xcc, rtrap_irq; \
+ .previous;
+
+#else
+
+#define TRAP_IRQ(routine, level) \
+ rdpr %pil, %g2; \
+ wrpr %g0, PIL_NORMAL_MAX, %pil; \
+ ba,pt %xcc, etrap_irq; \
+ rd %pc, %g7; \
+ mov level, %o0; \
+ call routine; \
+ add %sp, PTREGS_OFF, %o1; \
+ ba,a,pt %xcc, rtrap_irq;
+
+#endif
+
+#define TRAP_NMI_IRQ(routine, level) \
+ rdpr %pil, %g2; \
+ wrpr %g0, PIL_NMI, %pil; \
+ ba,pt %xcc, etrap_irq; \
+ rd %pc, %g7; \
+ mov level, %o0; \
+ call routine; \
+ add %sp, PTREGS_OFF, %o1; \
+ ba,a,pt %xcc, rtrap_nmi;
+
+#define TRAP_IVEC TRAP_NOSAVE(do_ivec)
+
+#define BTRAP(lvl) TRAP_ARG(bad_trap, lvl)
+
+#define BTRAPTL1(lvl) TRAPTL1_ARG(bad_trap_tl1, lvl)
+
+#define FLUSH_WINDOW_TRAP \
+ ba,pt %xcc, etrap; \
+ rd %pc, %g7; \
+ flushw; \
+ ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1; \
+ add %l1, 4, %l2; \
+ stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC]; \
+ ba,pt %xcc, rtrap; \
+ stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
+
+#ifdef CONFIG_KPROBES
+#define KPROBES_TRAP(lvl) TRAP_IRQ(kprobe_trap, lvl)
+#else
+#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
+#ifdef CONFIG_UPROBES
+#define UPROBES_TRAP(lvl) TRAP_ARG(uprobe_trap, lvl)
+#else
+#define UPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
+#ifdef CONFIG_KGDB
+#define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
+#else
+#define KGDB_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
+#define SUN4V_ITSB_MISS \
+ ldxa [%g0] ASI_SCRATCHPAD, %g2; \
+ ldx [%g2 + HV_FAULT_I_ADDR_OFFSET], %g4; \
+ ldx [%g2 + HV_FAULT_I_CTX_OFFSET], %g5; \
+ srlx %g4, 22, %g6; \
+ ba,pt %xcc, sun4v_itsb_miss; \
+ nop; \
+ nop; \
+ nop;
+
+#define SUN4V_DTSB_MISS \
+ ldxa [%g0] ASI_SCRATCHPAD, %g2; \
+ ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4; \
+ ldx [%g2 + HV_FAULT_D_CTX_OFFSET], %g5; \
+ srlx %g4, 22, %g6; \
+ ba,pt %xcc, sun4v_dtsb_miss; \
+ nop; \
+ nop; \
+ nop;
+
+#define SUN4V_MCD_PRECISE \
+ ldxa [%g0] ASI_SCRATCHPAD, %g2; \
+ ldx [%g2 + HV_FAULT_D_ADDR_OFFSET], %g4; \
+ ldx [%g2 + HV_FAULT_D_CTX_OFFSET], %g5; \
+ ba,pt %xcc, etrap; \
+ rd %pc, %g7; \
+ ba,pt %xcc, sun4v_mcd_detect_precise; \
+ nop; \
+ nop;
+
+/* Before touching these macros, you owe it to yourself to go and
+ * see how arch/sparc64/kernel/winfixup.S works... -DaveM
+ *
+ * For the user cases we used to use the %asi register, but
+ * it turns out that the "wr xxx, %asi" costs ~5 cycles, so
+ * now we use immediate ASI loads and stores instead. Kudos
+ * to Greg Onufer for pointing out this performance anomaly.
+ *
+ * Further note that we cannot use the g2, g4, g5, and g7 alternate
+ * globals in the spill routines, check out the save instruction in
+ * arch/sparc64/kernel/etrap.S to see what I mean about g2, and
+ * g4/g5 are the globals which are preserved by etrap processing
+ * for the caller of it. The g7 register is the return pc for
+ * etrap. Finally, g6 is the current thread register so we cannot
+ * us it in the spill handlers either. Most of these rules do not
+ * apply to fill processing, only g6 is not usable.
+ */
+
+/* Normal kernel spill */
+#define SPILL_0_NORMAL \
+ stx %l0, [%sp + STACK_BIAS + 0x00]; \
+ stx %l1, [%sp + STACK_BIAS + 0x08]; \
+ stx %l2, [%sp + STACK_BIAS + 0x10]; \
+ stx %l3, [%sp + STACK_BIAS + 0x18]; \
+ stx %l4, [%sp + STACK_BIAS + 0x20]; \
+ stx %l5, [%sp + STACK_BIAS + 0x28]; \
+ stx %l6, [%sp + STACK_BIAS + 0x30]; \
+ stx %l7, [%sp + STACK_BIAS + 0x38]; \
+ stx %i0, [%sp + STACK_BIAS + 0x40]; \
+ stx %i1, [%sp + STACK_BIAS + 0x48]; \
+ stx %i2, [%sp + STACK_BIAS + 0x50]; \
+ stx %i3, [%sp + STACK_BIAS + 0x58]; \
+ stx %i4, [%sp + STACK_BIAS + 0x60]; \
+ stx %i5, [%sp + STACK_BIAS + 0x68]; \
+ stx %i6, [%sp + STACK_BIAS + 0x70]; \
+ stx %i7, [%sp + STACK_BIAS + 0x78]; \
+ saved; retry; nop; nop; nop; nop; nop; nop; \
+ nop; nop; nop; nop; nop; nop; nop; nop;
+
+#define SPILL_0_NORMAL_ETRAP \
+etrap_kernel_spill: \
+ stx %l0, [%sp + STACK_BIAS + 0x00]; \
+ stx %l1, [%sp + STACK_BIAS + 0x08]; \
+ stx %l2, [%sp + STACK_BIAS + 0x10]; \
+ stx %l3, [%sp + STACK_BIAS + 0x18]; \
+ stx %l4, [%sp + STACK_BIAS + 0x20]; \
+ stx %l5, [%sp + STACK_BIAS + 0x28]; \
+ stx %l6, [%sp + STACK_BIAS + 0x30]; \
+ stx %l7, [%sp + STACK_BIAS + 0x38]; \
+ stx %i0, [%sp + STACK_BIAS + 0x40]; \
+ stx %i1, [%sp + STACK_BIAS + 0x48]; \
+ stx %i2, [%sp + STACK_BIAS + 0x50]; \
+ stx %i3, [%sp + STACK_BIAS + 0x58]; \
+ stx %i4, [%sp + STACK_BIAS + 0x60]; \
+ stx %i5, [%sp + STACK_BIAS + 0x68]; \
+ stx %i6, [%sp + STACK_BIAS + 0x70]; \
+ stx %i7, [%sp + STACK_BIAS + 0x78]; \
+ saved; \
+ sub %g1, 2, %g1; \
+ ba,pt %xcc, etrap_save; \
+ wrpr %g1, %cwp; \
+ nop; nop; nop; nop; nop; nop; nop; nop; \
+ nop; nop; nop; nop;
+
+/* Normal 64bit spill */
+#define SPILL_1_GENERIC(ASI) \
+ add %sp, STACK_BIAS + 0x00, %g1; \
+ stxa %l0, [%g1 + %g0] ASI; \
+ mov 0x08, %g3; \
+ stxa %l1, [%g1 + %g3] ASI; \
+ add %g1, 0x10, %g1; \
+ stxa %l2, [%g1 + %g0] ASI; \
+ stxa %l3, [%g1 + %g3] ASI; \
+ add %g1, 0x10, %g1; \
+ stxa %l4, [%g1 + %g0] ASI; \
+ stxa %l5, [%g1 + %g3] ASI; \
+ add %g1, 0x10, %g1; \
+ stxa %l6, [%g1 + %g0] ASI; \
+ stxa %l7, [%g1 + %g3] ASI; \
+ add %g1, 0x10, %g1; \
+ stxa %i0, [%g1 + %g0] ASI; \
+ stxa %i1, [%g1 + %g3] ASI; \
+ add %g1, 0x10, %g1; \
+ stxa %i2, [%g1 + %g0] ASI; \
+ stxa %i3, [%g1 + %g3] ASI; \
+ add %g1, 0x10, %g1; \
+ stxa %i4, [%g1 + %g0] ASI; \
+ stxa %i5, [%g1 + %g3] ASI; \
+ add %g1, 0x10, %g1; \
+ stxa %i6, [%g1 + %g0] ASI; \
+ stxa %i7, [%g1 + %g3] ASI; \
+ saved; \
+ retry; nop; nop; \
+ b,a,pt %xcc, spill_fixup_dax; \
+ b,a,pt %xcc, spill_fixup_mna; \
+ b,a,pt %xcc, spill_fixup;
+
+#define SPILL_1_GENERIC_ETRAP \
+etrap_user_spill_64bit: \
+ stxa %l0, [%sp + STACK_BIAS + 0x00] %asi; \
+ stxa %l1, [%sp + STACK_BIAS + 0x08] %asi; \
+ stxa %l2, [%sp + STACK_BIAS + 0x10] %asi; \
+ stxa %l3, [%sp + STACK_BIAS + 0x18] %asi; \
+ stxa %l4, [%sp + STACK_BIAS + 0x20] %asi; \
+ stxa %l5, [%sp + STACK_BIAS + 0x28] %asi; \
+ stxa %l6, [%sp + STACK_BIAS + 0x30] %asi; \
+ stxa %l7, [%sp + STACK_BIAS + 0x38] %asi; \
+ stxa %i0, [%sp + STACK_BIAS + 0x40] %asi; \
+ stxa %i1, [%sp + STACK_BIAS + 0x48] %asi; \
+ stxa %i2, [%sp + STACK_BIAS + 0x50] %asi; \
+ stxa %i3, [%sp + STACK_BIAS + 0x58] %asi; \
+ stxa %i4, [%sp + STACK_BIAS + 0x60] %asi; \
+ stxa %i5, [%sp + STACK_BIAS + 0x68] %asi; \
+ stxa %i6, [%sp + STACK_BIAS + 0x70] %asi; \
+ stxa %i7, [%sp + STACK_BIAS + 0x78] %asi; \
+ saved; \
+ sub %g1, 2, %g1; \
+ ba,pt %xcc, etrap_save; \
+ wrpr %g1, %cwp; \
+ nop; nop; nop; nop; nop; \
+ nop; nop; nop; nop; \
+ ba,a,pt %xcc, etrap_spill_fixup_64bit; \
+ ba,a,pt %xcc, etrap_spill_fixup_64bit; \
+ ba,a,pt %xcc, etrap_spill_fixup_64bit;
+
+#define SPILL_1_GENERIC_ETRAP_FIXUP \
+etrap_spill_fixup_64bit: \
+ ldub [%g6 + TI_WSAVED], %g1; \
+ sll %g1, 3, %g3; \
+ add %g6, %g3, %g3; \
+ stx %sp, [%g3 + TI_RWIN_SPTRS]; \
+ sll %g1, 7, %g3; \
+ add %g6, %g3, %g3; \
+ stx %l0, [%g3 + TI_REG_WINDOW + 0x00]; \
+ stx %l1, [%g3 + TI_REG_WINDOW + 0x08]; \
+ stx %l2, [%g3 + TI_REG_WINDOW + 0x10]; \
+ stx %l3, [%g3 + TI_REG_WINDOW + 0x18]; \
+ stx %l4, [%g3 + TI_REG_WINDOW + 0x20]; \
+ stx %l5, [%g3 + TI_REG_WINDOW + 0x28]; \
+ stx %l6, [%g3 + TI_REG_WINDOW + 0x30]; \
+ stx %l7, [%g3 + TI_REG_WINDOW + 0x38]; \
+ stx %i0, [%g3 + TI_REG_WINDOW + 0x40]; \
+ stx %i1, [%g3 + TI_REG_WINDOW + 0x48]; \
+ stx %i2, [%g3 + TI_REG_WINDOW + 0x50]; \
+ stx %i3, [%g3 + TI_REG_WINDOW + 0x58]; \
+ stx %i4, [%g3 + TI_REG_WINDOW + 0x60]; \
+ stx %i5, [%g3 + TI_REG_WINDOW + 0x68]; \
+ stx %i6, [%g3 + TI_REG_WINDOW + 0x70]; \
+ stx %i7, [%g3 + TI_REG_WINDOW + 0x78]; \
+ add %g1, 1, %g1; \
+ stb %g1, [%g6 + TI_WSAVED]; \
+ saved; \
+ rdpr %cwp, %g1; \
+ sub %g1, 2, %g1; \
+ ba,pt %xcc, etrap_save; \
+ wrpr %g1, %cwp; \
+ nop; nop; nop
+
+/* Normal 32bit spill */
+#define SPILL_2_GENERIC(ASI) \
+ and %sp, 1, %g3; \
+ brnz,pn %g3, (. - (128 + 4)); \
+ srl %sp, 0, %sp; \
+ stwa %l0, [%sp + %g0] ASI; \
+ mov 0x04, %g3; \
+ stwa %l1, [%sp + %g3] ASI; \
+ add %sp, 0x08, %g1; \
+ stwa %l2, [%g1 + %g0] ASI; \
+ stwa %l3, [%g1 + %g3] ASI; \
+ add %g1, 0x08, %g1; \
+ stwa %l4, [%g1 + %g0] ASI; \
+ stwa %l5, [%g1 + %g3] ASI; \
+ add %g1, 0x08, %g1; \
+ stwa %l6, [%g1 + %g0] ASI; \
+ stwa %l7, [%g1 + %g3] ASI; \
+ add %g1, 0x08, %g1; \
+ stwa %i0, [%g1 + %g0] ASI; \
+ stwa %i1, [%g1 + %g3] ASI; \
+ add %g1, 0x08, %g1; \
+ stwa %i2, [%g1 + %g0] ASI; \
+ stwa %i3, [%g1 + %g3] ASI; \
+ add %g1, 0x08, %g1; \
+ stwa %i4, [%g1 + %g0] ASI; \
+ stwa %i5, [%g1 + %g3] ASI; \
+ add %g1, 0x08, %g1; \
+ stwa %i6, [%g1 + %g0] ASI; \
+ stwa %i7, [%g1 + %g3] ASI; \
+ saved; \
+ retry; \
+ b,a,pt %xcc, spill_fixup_dax; \
+ b,a,pt %xcc, spill_fixup_mna; \
+ b,a,pt %xcc, spill_fixup;
+
+#define SPILL_2_GENERIC_ETRAP \
+etrap_user_spill_32bit: \
+ and %sp, 1, %g3; \
+ brnz,pn %g3, etrap_user_spill_64bit; \
+ srl %sp, 0, %sp; \
+ stwa %l0, [%sp + 0x00] %asi; \
+ stwa %l1, [%sp + 0x04] %asi; \
+ stwa %l2, [%sp + 0x08] %asi; \
+ stwa %l3, [%sp + 0x0c] %asi; \
+ stwa %l4, [%sp + 0x10] %asi; \
+ stwa %l5, [%sp + 0x14] %asi; \
+ stwa %l6, [%sp + 0x18] %asi; \
+ stwa %l7, [%sp + 0x1c] %asi; \
+ stwa %i0, [%sp + 0x20] %asi; \
+ stwa %i1, [%sp + 0x24] %asi; \
+ stwa %i2, [%sp + 0x28] %asi; \
+ stwa %i3, [%sp + 0x2c] %asi; \
+ stwa %i4, [%sp + 0x30] %asi; \
+ stwa %i5, [%sp + 0x34] %asi; \
+ stwa %i6, [%sp + 0x38] %asi; \
+ stwa %i7, [%sp + 0x3c] %asi; \
+ saved; \
+ sub %g1, 2, %g1; \
+ ba,pt %xcc, etrap_save; \
+ wrpr %g1, %cwp; \
+ nop; nop; nop; nop; \
+ nop; nop; \
+ ba,a,pt %xcc, etrap_spill_fixup_32bit; \
+ ba,a,pt %xcc, etrap_spill_fixup_32bit; \
+ ba,a,pt %xcc, etrap_spill_fixup_32bit;
+
+#define SPILL_2_GENERIC_ETRAP_FIXUP \
+etrap_spill_fixup_32bit: \
+ ldub [%g6 + TI_WSAVED], %g1; \
+ sll %g1, 3, %g3; \
+ add %g6, %g3, %g3; \
+ stx %sp, [%g3 + TI_RWIN_SPTRS]; \
+ sll %g1, 7, %g3; \
+ add %g6, %g3, %g3; \
+ stw %l0, [%g3 + TI_REG_WINDOW + 0x00]; \
+ stw %l1, [%g3 + TI_REG_WINDOW + 0x04]; \
+ stw %l2, [%g3 + TI_REG_WINDOW + 0x08]; \
+ stw %l3, [%g3 + TI_REG_WINDOW + 0x0c]; \
+ stw %l4, [%g3 + TI_REG_WINDOW + 0x10]; \
+ stw %l5, [%g3 + TI_REG_WINDOW + 0x14]; \
+ stw %l6, [%g3 + TI_REG_WINDOW + 0x18]; \
+ stw %l7, [%g3 + TI_REG_WINDOW + 0x1c]; \
+ stw %i0, [%g3 + TI_REG_WINDOW + 0x20]; \
+ stw %i1, [%g3 + TI_REG_WINDOW + 0x24]; \
+ stw %i2, [%g3 + TI_REG_WINDOW + 0x28]; \
+ stw %i3, [%g3 + TI_REG_WINDOW + 0x2c]; \
+ stw %i4, [%g3 + TI_REG_WINDOW + 0x30]; \
+ stw %i5, [%g3 + TI_REG_WINDOW + 0x34]; \
+ stw %i6, [%g3 + TI_REG_WINDOW + 0x38]; \
+ stw %i7, [%g3 + TI_REG_WINDOW + 0x3c]; \
+ add %g1, 1, %g1; \
+ stb %g1, [%g6 + TI_WSAVED]; \
+ saved; \
+ rdpr %cwp, %g1; \
+ sub %g1, 2, %g1; \
+ ba,pt %xcc, etrap_save; \
+ wrpr %g1, %cwp; \
+ nop; nop; nop
+
+#define SPILL_1_NORMAL SPILL_1_GENERIC(ASI_AIUP)
+#define SPILL_2_NORMAL SPILL_2_GENERIC(ASI_AIUP)
+#define SPILL_3_NORMAL SPILL_0_NORMAL
+#define SPILL_4_NORMAL SPILL_0_NORMAL
+#define SPILL_5_NORMAL SPILL_0_NORMAL
+#define SPILL_6_NORMAL SPILL_0_NORMAL
+#define SPILL_7_NORMAL SPILL_0_NORMAL
+
+#define SPILL_0_OTHER SPILL_0_NORMAL
+#define SPILL_1_OTHER SPILL_1_GENERIC(ASI_AIUS)
+#define SPILL_2_OTHER SPILL_2_GENERIC(ASI_AIUS)
+#define SPILL_3_OTHER SPILL_3_NORMAL
+#define SPILL_4_OTHER SPILL_4_NORMAL
+#define SPILL_5_OTHER SPILL_5_NORMAL
+#define SPILL_6_OTHER SPILL_6_NORMAL
+#define SPILL_7_OTHER SPILL_7_NORMAL
+
+/* Normal kernel fill */
+#define FILL_0_NORMAL \
+ ldx [%sp + STACK_BIAS + 0x00], %l0; \
+ ldx [%sp + STACK_BIAS + 0x08], %l1; \
+ ldx [%sp + STACK_BIAS + 0x10], %l2; \
+ ldx [%sp + STACK_BIAS + 0x18], %l3; \
+ ldx [%sp + STACK_BIAS + 0x20], %l4; \
+ ldx [%sp + STACK_BIAS + 0x28], %l5; \
+ ldx [%sp + STACK_BIAS + 0x30], %l6; \
+ ldx [%sp + STACK_BIAS + 0x38], %l7; \
+ ldx [%sp + STACK_BIAS + 0x40], %i0; \
+ ldx [%sp + STACK_BIAS + 0x48], %i1; \
+ ldx [%sp + STACK_BIAS + 0x50], %i2; \
+ ldx [%sp + STACK_BIAS + 0x58], %i3; \
+ ldx [%sp + STACK_BIAS + 0x60], %i4; \
+ ldx [%sp + STACK_BIAS + 0x68], %i5; \
+ ldx [%sp + STACK_BIAS + 0x70], %i6; \
+ ldx [%sp + STACK_BIAS + 0x78], %i7; \
+ restored; retry; nop; nop; nop; nop; nop; nop; \
+ nop; nop; nop; nop; nop; nop; nop; nop;
+
+#define FILL_0_NORMAL_RTRAP \
+kern_rtt_fill: \
+ rdpr %cwp, %g1; \
+ sub %g1, 1, %g1; \
+ wrpr %g1, %cwp; \
+ ldx [%sp + STACK_BIAS + 0x00], %l0; \
+ ldx [%sp + STACK_BIAS + 0x08], %l1; \
+ ldx [%sp + STACK_BIAS + 0x10], %l2; \
+ ldx [%sp + STACK_BIAS + 0x18], %l3; \
+ ldx [%sp + STACK_BIAS + 0x20], %l4; \
+ ldx [%sp + STACK_BIAS + 0x28], %l5; \
+ ldx [%sp + STACK_BIAS + 0x30], %l6; \
+ ldx [%sp + STACK_BIAS + 0x38], %l7; \
+ ldx [%sp + STACK_BIAS + 0x40], %i0; \
+ ldx [%sp + STACK_BIAS + 0x48], %i1; \
+ ldx [%sp + STACK_BIAS + 0x50], %i2; \
+ ldx [%sp + STACK_BIAS + 0x58], %i3; \
+ ldx [%sp + STACK_BIAS + 0x60], %i4; \
+ ldx [%sp + STACK_BIAS + 0x68], %i5; \
+ ldx [%sp + STACK_BIAS + 0x70], %i6; \
+ ldx [%sp + STACK_BIAS + 0x78], %i7; \
+ restored; \
+ add %g1, 1, %g1; \
+ ba,pt %xcc, kern_rtt_restore; \
+ wrpr %g1, %cwp; \
+ nop; nop; nop; nop; nop; \
+ nop; nop; nop; nop;
+
+
+/* Normal 64bit fill */
+#define FILL_1_GENERIC(ASI) \
+ add %sp, STACK_BIAS + 0x00, %g1; \
+ ldxa [%g1 + %g0] ASI, %l0; \
+ mov 0x08, %g2; \
+ mov 0x10, %g3; \
+ ldxa [%g1 + %g2] ASI, %l1; \
+ mov 0x18, %g5; \
+ ldxa [%g1 + %g3] ASI, %l2; \
+ ldxa [%g1 + %g5] ASI, %l3; \
+ add %g1, 0x20, %g1; \
+ ldxa [%g1 + %g0] ASI, %l4; \
+ ldxa [%g1 + %g2] ASI, %l5; \
+ ldxa [%g1 + %g3] ASI, %l6; \
+ ldxa [%g1 + %g5] ASI, %l7; \
+ add %g1, 0x20, %g1; \
+ ldxa [%g1 + %g0] ASI, %i0; \
+ ldxa [%g1 + %g2] ASI, %i1; \
+ ldxa [%g1 + %g3] ASI, %i2; \
+ ldxa [%g1 + %g5] ASI, %i3; \
+ add %g1, 0x20, %g1; \
+ ldxa [%g1 + %g0] ASI, %i4; \
+ ldxa [%g1 + %g2] ASI, %i5; \
+ ldxa [%g1 + %g3] ASI, %i6; \
+ ldxa [%g1 + %g5] ASI, %i7; \
+ restored; \
+ retry; nop; nop; nop; nop; \
+ b,a,pt %xcc, fill_fixup_dax; \
+ b,a,pt %xcc, fill_fixup_mna; \
+ b,a,pt %xcc, fill_fixup;
+
+#define FILL_1_GENERIC_RTRAP \
+user_rtt_fill_64bit: \
+ ldxa [%sp + STACK_BIAS + 0x00] %asi, %l0; \
+ ldxa [%sp + STACK_BIAS + 0x08] %asi, %l1; \
+ ldxa [%sp + STACK_BIAS + 0x10] %asi, %l2; \
+ ldxa [%sp + STACK_BIAS + 0x18] %asi, %l3; \
+ ldxa [%sp + STACK_BIAS + 0x20] %asi, %l4; \
+ ldxa [%sp + STACK_BIAS + 0x28] %asi, %l5; \
+ ldxa [%sp + STACK_BIAS + 0x30] %asi, %l6; \
+ ldxa [%sp + STACK_BIAS + 0x38] %asi, %l7; \
+ ldxa [%sp + STACK_BIAS + 0x40] %asi, %i0; \
+ ldxa [%sp + STACK_BIAS + 0x48] %asi, %i1; \
+ ldxa [%sp + STACK_BIAS + 0x50] %asi, %i2; \
+ ldxa [%sp + STACK_BIAS + 0x58] %asi, %i3; \
+ ldxa [%sp + STACK_BIAS + 0x60] %asi, %i4; \
+ ldxa [%sp + STACK_BIAS + 0x68] %asi, %i5; \
+ ldxa [%sp + STACK_BIAS + 0x70] %asi, %i6; \
+ ldxa [%sp + STACK_BIAS + 0x78] %asi, %i7; \
+ ba,pt %xcc, user_rtt_pre_restore; \
+ restored; \
+ nop; nop; nop; nop; nop; nop; \
+ nop; nop; nop; nop; nop; \
+ ba,a,pt %xcc, user_rtt_fill_fixup_dax; \
+ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \
+ ba,a,pt %xcc, user_rtt_fill_fixup;
+
+
+/* Normal 32bit fill */
+#define FILL_2_GENERIC(ASI) \
+ and %sp, 1, %g3; \
+ brnz,pn %g3, (. - (128 + 4)); \
+ srl %sp, 0, %sp; \
+ lduwa [%sp + %g0] ASI, %l0; \
+ mov 0x04, %g2; \
+ mov 0x08, %g3; \
+ lduwa [%sp + %g2] ASI, %l1; \
+ mov 0x0c, %g5; \
+ lduwa [%sp + %g3] ASI, %l2; \
+ lduwa [%sp + %g5] ASI, %l3; \
+ add %sp, 0x10, %g1; \
+ lduwa [%g1 + %g0] ASI, %l4; \
+ lduwa [%g1 + %g2] ASI, %l5; \
+ lduwa [%g1 + %g3] ASI, %l6; \
+ lduwa [%g1 + %g5] ASI, %l7; \
+ add %g1, 0x10, %g1; \
+ lduwa [%g1 + %g0] ASI, %i0; \
+ lduwa [%g1 + %g2] ASI, %i1; \
+ lduwa [%g1 + %g3] ASI, %i2; \
+ lduwa [%g1 + %g5] ASI, %i3; \
+ add %g1, 0x10, %g1; \
+ lduwa [%g1 + %g0] ASI, %i4; \
+ lduwa [%g1 + %g2] ASI, %i5; \
+ lduwa [%g1 + %g3] ASI, %i6; \
+ lduwa [%g1 + %g5] ASI, %i7; \
+ restored; \
+ retry; nop; nop; \
+ b,a,pt %xcc, fill_fixup_dax; \
+ b,a,pt %xcc, fill_fixup_mna; \
+ b,a,pt %xcc, fill_fixup;
+
+#define FILL_2_GENERIC_RTRAP \
+user_rtt_fill_32bit: \
+ and %sp, 1, %g3; \
+ brnz,pn %g3, user_rtt_fill_64bit; \
+ srl %sp, 0, %sp; \
+ lduwa [%sp + 0x00] %asi, %l0; \
+ lduwa [%sp + 0x04] %asi, %l1; \
+ lduwa [%sp + 0x08] %asi, %l2; \
+ lduwa [%sp + 0x0c] %asi, %l3; \
+ lduwa [%sp + 0x10] %asi, %l4; \
+ lduwa [%sp + 0x14] %asi, %l5; \
+ lduwa [%sp + 0x18] %asi, %l6; \
+ lduwa [%sp + 0x1c] %asi, %l7; \
+ lduwa [%sp + 0x20] %asi, %i0; \
+ lduwa [%sp + 0x24] %asi, %i1; \
+ lduwa [%sp + 0x28] %asi, %i2; \
+ lduwa [%sp + 0x2c] %asi, %i3; \
+ lduwa [%sp + 0x30] %asi, %i4; \
+ lduwa [%sp + 0x34] %asi, %i5; \
+ lduwa [%sp + 0x38] %asi, %i6; \
+ lduwa [%sp + 0x3c] %asi, %i7; \
+ ba,pt %xcc, user_rtt_pre_restore; \
+ restored; \
+ nop; nop; nop; nop; nop; \
+ nop; nop; nop; \
+ ba,a,pt %xcc, user_rtt_fill_fixup_dax; \
+ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \
+ ba,a,pt %xcc, user_rtt_fill_fixup;
+
+
+#define FILL_1_NORMAL FILL_1_GENERIC(ASI_AIUP)
+#define FILL_2_NORMAL FILL_2_GENERIC(ASI_AIUP)
+#define FILL_3_NORMAL FILL_0_NORMAL
+#define FILL_4_NORMAL FILL_0_NORMAL
+#define FILL_5_NORMAL FILL_0_NORMAL
+#define FILL_6_NORMAL FILL_0_NORMAL
+#define FILL_7_NORMAL FILL_0_NORMAL
+
+#define FILL_0_OTHER FILL_0_NORMAL
+#define FILL_1_OTHER FILL_1_GENERIC(ASI_AIUS)
+#define FILL_2_OTHER FILL_2_GENERIC(ASI_AIUS)
+#define FILL_3_OTHER FILL_3_NORMAL
+#define FILL_4_OTHER FILL_4_NORMAL
+#define FILL_5_OTHER FILL_5_NORMAL
+#define FILL_6_OTHER FILL_6_NORMAL
+#define FILL_7_OTHER FILL_7_NORMAL
+
+#endif /* !(_SPARC64_TTABLE_H) */
diff --git a/arch/sparc/include/asm/turbosparc.h b/arch/sparc/include/asm/turbosparc.h
new file mode 100644
index 000000000..23df777f9
--- /dev/null
+++ b/arch/sparc/include/asm/turbosparc.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * turbosparc.h: Defines specific to the TurboSparc module.
+ * This is SRMMU stuff.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+#ifndef _SPARC_TURBOSPARC_H
+#define _SPARC_TURBOSPARC_H
+
+#include <asm/asi.h>
+#include <asm/pgtsrmmu.h>
+
+/* Bits in the SRMMU control register for TurboSparc modules.
+ *
+ * -------------------------------------------------------------------
+ * |impl-vers| RSV| PMC |PE|PC| RSV |BM| RFR |IC|DC|PSO|RSV|ICS|NF|ME|
+ * -------------------------------------------------------------------
+ * 31 24 23-21 20-19 18 17 16-15 14 13-10 9 8 7 6-3 2 1 0
+ *
+ * BM: Boot Mode -- 0 = not in boot mode, 1 = in boot mode
+ *
+ * This indicates whether the TurboSparc is in boot-mode or not.
+ *
+ * IC: Instruction Cache -- 0 = off, 1 = on
+ * DC: Data Cache -- 0 = off, 1 = 0n
+ *
+ * These bits enable the on-cpu TurboSparc split I/D caches.
+ *
+ * ICS: ICache Snooping -- 0 = disable, 1 = enable snooping of icache
+ * NF: No Fault -- 0 = faults generate traps, 1 = faults don't trap
+ * ME: MMU enable -- 0 = mmu not translating, 1 = mmu translating
+ *
+ */
+
+#define TURBOSPARC_MMUENABLE 0x00000001
+#define TURBOSPARC_NOFAULT 0x00000002
+#define TURBOSPARC_ICSNOOP 0x00000004
+#define TURBOSPARC_PSO 0x00000080
+#define TURBOSPARC_DCENABLE 0x00000100 /* Enable data cache */
+#define TURBOSPARC_ICENABLE 0x00000200 /* Enable instruction cache */
+#define TURBOSPARC_BMODE 0x00004000
+#define TURBOSPARC_PARITYODD 0x00020000 /* Parity odd, if enabled */
+#define TURBOSPARC_PCENABLE 0x00040000 /* Enable parity checking */
+
+/* Bits in the CPU configuration register for TurboSparc modules.
+ *
+ * -------------------------------------------------------
+ * |IOClk|SNP|AXClk| RAH | WS | RSV |SBC|WT|uS2|SE|SCC|
+ * -------------------------------------------------------
+ * 31 30 29-28 27-26 25-23 22-8 7-6 5 4 3 2-0
+ *
+ */
+
+#define TURBOSPARC_SCENABLE 0x00000008 /* Secondary cache enable */
+#define TURBOSPARC_uS2 0x00000010 /* Swift compatibility mode */
+#define TURBOSPARC_WTENABLE 0x00000020 /* Write thru for dcache */
+#define TURBOSPARC_SNENABLE 0x40000000 /* DVMA snoop enable */
+
+#ifndef __ASSEMBLY__
+
+/* Bits [13:5] select one of 512 instruction cache tags */
+static inline void turbosparc_inv_insn_tag(unsigned long addr)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_TXTC_TAG)
+ : "memory");
+}
+
+/* Bits [13:5] select one of 512 data cache tags */
+static inline void turbosparc_inv_data_tag(unsigned long addr)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (addr), "i" (ASI_M_DATAC_TAG)
+ : "memory");
+}
+
+static inline void turbosparc_flush_icache(void)
+{
+ unsigned long addr;
+
+ for (addr = 0; addr < 0x4000; addr += 0x20)
+ turbosparc_inv_insn_tag(addr);
+}
+
+static inline void turbosparc_flush_dcache(void)
+{
+ unsigned long addr;
+
+ for (addr = 0; addr < 0x4000; addr += 0x20)
+ turbosparc_inv_data_tag(addr);
+}
+
+static inline void turbosparc_idflash_clear(void)
+{
+ unsigned long addr;
+
+ for (addr = 0; addr < 0x4000; addr += 0x20) {
+ turbosparc_inv_insn_tag(addr);
+ turbosparc_inv_data_tag(addr);
+ }
+}
+
+static inline void turbosparc_set_ccreg(unsigned long regval)
+{
+ __asm__ __volatile__("sta %0, [%1] %2\n\t"
+ : /* no outputs */
+ : "r" (regval), "r" (0x600), "i" (ASI_M_MMUREGS)
+ : "memory");
+}
+
+static inline unsigned long turbosparc_get_ccreg(void)
+{
+ unsigned long regval;
+
+ __asm__ __volatile__("lda [%1] %2, %0\n\t"
+ : "=r" (regval)
+ : "r" (0x600), "i" (ASI_M_MMUREGS));
+ return regval;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !(_SPARC_TURBOSPARC_H) */
diff --git a/arch/sparc/include/asm/uaccess.h b/arch/sparc/include/asm/uaccess.h
new file mode 100644
index 000000000..ee75f69e3
--- /dev/null
+++ b/arch/sparc/include/asm/uaccess.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_UACCESS_H
+#define ___ASM_SPARC_UACCESS_H
+
+#include <asm/extable.h>
+
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/uaccess_64.h>
+#else
+#include <asm/uaccess_32.h>
+#endif
+
+long strncpy_from_user(char *dest, const char __user *src, long count);
+
+#endif
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h
new file mode 100644
index 000000000..9fd6c5364
--- /dev/null
+++ b/arch/sparc/include/asm/uaccess_32.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * uaccess.h: User space memore access functions.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+
+#include <linux/compiler.h>
+#include <linux/string.h>
+
+#include <asm/processor.h>
+#include <asm-generic/access_ok.h>
+
+/* Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the ugliness from the user.
+ */
+#define put_user(x, ptr) ({ \
+ void __user *__pu_addr = (ptr); \
+ __chk_user_ptr(ptr); \
+ __put_user_check((__typeof__(*(ptr)))(x), __pu_addr, sizeof(*(ptr))); \
+})
+
+#define get_user(x, ptr) ({ \
+ const void __user *__gu_addr = (ptr); \
+ __chk_user_ptr(ptr); \
+ __get_user_check((x), __gu_addr, sizeof(*(ptr)), __typeof__(*(ptr))); \
+})
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x, ptr) \
+ __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+#define __get_user(x, ptr) \
+ __get_user_nocheck((x), (ptr), sizeof(*(ptr)), __typeof__(*(ptr)))
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) ((struct __large_struct __user *)(x))
+
+#define __put_user_check(x, addr, size) ({ \
+ register int __pu_ret; \
+ if (__access_ok(addr, size)) { \
+ switch (size) { \
+ case 1: \
+ __put_user_asm(x, b, addr, __pu_ret); \
+ break; \
+ case 2: \
+ __put_user_asm(x, h, addr, __pu_ret); \
+ break; \
+ case 4: \
+ __put_user_asm(x, , addr, __pu_ret); \
+ break; \
+ case 8: \
+ __put_user_asm(x, d, addr, __pu_ret); \
+ break; \
+ default: \
+ __pu_ret = __put_user_bad(); \
+ break; \
+ } \
+ } else { \
+ __pu_ret = -EFAULT; \
+ } \
+ __pu_ret; \
+})
+
+#define __put_user_nocheck(x, addr, size) ({ \
+ register int __pu_ret; \
+ switch (size) { \
+ case 1: __put_user_asm(x, b, addr, __pu_ret); break; \
+ case 2: __put_user_asm(x, h, addr, __pu_ret); break; \
+ case 4: __put_user_asm(x, , addr, __pu_ret); break; \
+ case 8: __put_user_asm(x, d, addr, __pu_ret); break; \
+ default: __pu_ret = __put_user_bad(); break; \
+ } \
+ __pu_ret; \
+})
+
+#define __put_user_asm(x, size, addr, ret) \
+__asm__ __volatile__( \
+ "/* Put user asm, inline. */\n" \
+ "1:\t" "st"#size " %1, %2\n\t" \
+ "clr %0\n" \
+ "2:\n\n\t" \
+ ".section .fixup,#alloc,#execinstr\n\t" \
+ ".align 4\n" \
+ "3:\n\t" \
+ "b 2b\n\t" \
+ " mov %3, %0\n\t" \
+ ".previous\n\n\t" \
+ ".section __ex_table,#alloc\n\t" \
+ ".align 4\n\t" \
+ ".word 1b, 3b\n\t" \
+ ".previous\n\n\t" \
+ : "=&r" (ret) : "r" (x), "m" (*__m(addr)), \
+ "i" (-EFAULT))
+
+int __put_user_bad(void);
+
+#define __get_user_check(x, addr, size, type) ({ \
+ register int __gu_ret; \
+ register unsigned long __gu_val; \
+ if (__access_ok(addr, size)) { \
+ switch (size) { \
+ case 1: \
+ __get_user_asm(__gu_val, ub, addr, __gu_ret); \
+ break; \
+ case 2: \
+ __get_user_asm(__gu_val, uh, addr, __gu_ret); \
+ break; \
+ case 4: \
+ __get_user_asm(__gu_val, , addr, __gu_ret); \
+ break; \
+ case 8: \
+ __get_user_asm(__gu_val, d, addr, __gu_ret); \
+ break; \
+ default: \
+ __gu_val = 0; \
+ __gu_ret = __get_user_bad(); \
+ break; \
+ } \
+ } else { \
+ __gu_val = 0; \
+ __gu_ret = -EFAULT; \
+ } \
+ x = (__force type) __gu_val; \
+ __gu_ret; \
+})
+
+#define __get_user_nocheck(x, addr, size, type) ({ \
+ register int __gu_ret; \
+ register unsigned long __gu_val; \
+ switch (size) { \
+ case 1: __get_user_asm(__gu_val, ub, addr, __gu_ret); break; \
+ case 2: __get_user_asm(__gu_val, uh, addr, __gu_ret); break; \
+ case 4: __get_user_asm(__gu_val, , addr, __gu_ret); break; \
+ case 8: __get_user_asm(__gu_val, d, addr, __gu_ret); break; \
+ default: \
+ __gu_val = 0; \
+ __gu_ret = __get_user_bad(); \
+ break; \
+ } \
+ x = (__force type) __gu_val; \
+ __gu_ret; \
+})
+
+#define __get_user_asm(x, size, addr, ret) \
+__asm__ __volatile__( \
+ "/* Get user asm, inline. */\n" \
+ "1:\t" "ld"#size " %2, %1\n\t" \
+ "clr %0\n" \
+ "2:\n\n\t" \
+ ".section .fixup,#alloc,#execinstr\n\t" \
+ ".align 4\n" \
+ "3:\n\t" \
+ "clr %1\n\t" \
+ "b 2b\n\t" \
+ " mov %3, %0\n\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,#alloc\n\t" \
+ ".align 4\n\t" \
+ ".word 1b, 3b\n\n\t" \
+ ".previous\n\t" \
+ : "=&r" (ret), "=&r" (x) : "m" (*__m(addr)), \
+ "i" (-EFAULT))
+
+int __get_user_bad(void);
+
+unsigned long __copy_user(void __user *to, const void __user *from, unsigned long size);
+
+static inline unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+ return __copy_user(to, (__force void __user *) from, n);
+}
+
+static inline unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+ return __copy_user((__force void __user *) to, from, n);
+}
+
+#define INLINE_COPY_FROM_USER
+#define INLINE_COPY_TO_USER
+
+static inline unsigned long __clear_user(void __user *addr, unsigned long size)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__ (
+ "mov %2, %%o1\n"
+ "call __bzero\n\t"
+ " mov %1, %%o0\n\t"
+ "mov %%o0, %0\n"
+ : "=r" (ret) : "r" (addr), "r" (size) :
+ "o0", "o1", "o2", "o3", "o4", "o5", "o7",
+ "g1", "g2", "g3", "g4", "g5", "g7", "cc");
+
+ return ret;
+}
+
+static inline unsigned long clear_user(void __user *addr, unsigned long n)
+{
+ if (n && __access_ok(addr, n))
+ return __clear_user(addr, n);
+ else
+ return n;
+}
+
+__must_check long strnlen_user(const char __user *str, long n);
+
+#endif /* _ASM_UACCESS_H */
diff --git a/arch/sparc/include/asm/uaccess_64.h b/arch/sparc/include/asm/uaccess_64.h
new file mode 100644
index 000000000..b825a5dd0
--- /dev/null
+++ b/arch/sparc/include/asm/uaccess_64.h
@@ -0,0 +1,252 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_UACCESS_H
+#define _ASM_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+
+#include <linux/compiler.h>
+#include <linux/string.h>
+#include <linux/mm_types.h>
+#include <asm/asi.h>
+#include <asm/spitfire.h>
+#include <asm/pgtable.h>
+
+#include <asm/processor.h>
+#include <asm-generic/access_ok.h>
+
+/*
+ * Sparc64 is segmented, though more like the M68K than the I386.
+ * We use the secondary ASI to address user memory, which references a
+ * completely different VM map, thus there is zero chance of the user
+ * doing something queer and tricking us into poking kernel memory.
+ */
+
+/*
+ * Test whether a block of memory is a valid user space address.
+ * Returns 0 if the range is valid, nonzero otherwise.
+ */
+static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, unsigned long limit)
+{
+ if (__builtin_constant_p(size))
+ return addr > limit - size;
+
+ addr += size;
+ if (addr < size)
+ return true;
+
+ return addr > limit;
+}
+
+#define __range_not_ok(addr, size, limit) \
+({ \
+ __chk_user_ptr(addr); \
+ __chk_range_not_ok((unsigned long __force)(addr), size, limit); \
+})
+
+void __retl_efault(void);
+
+/* Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the ugliness from the user.
+ */
+#define put_user(x, ptr) ({ \
+ unsigned long __pu_addr = (unsigned long)(ptr); \
+ __chk_user_ptr(ptr); \
+ __put_user_nocheck((__typeof__(*(ptr)))(x), __pu_addr, sizeof(*(ptr)));\
+})
+
+#define get_user(x, ptr) ({ \
+ unsigned long __gu_addr = (unsigned long)(ptr); \
+ __chk_user_ptr(ptr); \
+ __get_user_nocheck((x), __gu_addr, sizeof(*(ptr)), __typeof__(*(ptr)));\
+})
+
+#define __put_user(x, ptr) put_user(x, ptr)
+#define __get_user(x, ptr) get_user(x, ptr)
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) ((struct __large_struct *)(x))
+
+#define __put_kernel_nofault(dst, src, type, label) \
+do { \
+ type *addr = (type __force *)(dst); \
+ type data = *(type *)src; \
+ register int __pu_ret; \
+ switch (sizeof(type)) { \
+ case 1: __put_kernel_asm(data, b, addr, __pu_ret); break; \
+ case 2: __put_kernel_asm(data, h, addr, __pu_ret); break; \
+ case 4: __put_kernel_asm(data, w, addr, __pu_ret); break; \
+ case 8: __put_kernel_asm(data, x, addr, __pu_ret); break; \
+ default: __pu_ret = __put_user_bad(); break; \
+ } \
+ if (__pu_ret) \
+ goto label; \
+} while (0)
+
+#define __put_kernel_asm(x, size, addr, ret) \
+__asm__ __volatile__( \
+ "/* Put kernel asm, inline. */\n" \
+ "1:\t" "st"#size " %1, [%2]\n\t" \
+ "clr %0\n" \
+ "2:\n\n\t" \
+ ".section .fixup,#alloc,#execinstr\n\t" \
+ ".align 4\n" \
+ "3:\n\t" \
+ "sethi %%hi(2b), %0\n\t" \
+ "jmpl %0 + %%lo(2b), %%g0\n\t" \
+ " mov %3, %0\n\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,\"a\"\n\t" \
+ ".align 4\n\t" \
+ ".word 1b, 3b\n\t" \
+ ".previous\n\n\t" \
+ : "=r" (ret) : "r" (x), "r" (__m(addr)), \
+ "i" (-EFAULT))
+
+#define __put_user_nocheck(data, addr, size) ({ \
+ register int __pu_ret; \
+ switch (size) { \
+ case 1: __put_user_asm(data, b, addr, __pu_ret); break; \
+ case 2: __put_user_asm(data, h, addr, __pu_ret); break; \
+ case 4: __put_user_asm(data, w, addr, __pu_ret); break; \
+ case 8: __put_user_asm(data, x, addr, __pu_ret); break; \
+ default: __pu_ret = __put_user_bad(); break; \
+ } \
+ __pu_ret; \
+})
+
+#define __put_user_asm(x, size, addr, ret) \
+__asm__ __volatile__( \
+ "/* Put user asm, inline. */\n" \
+ "1:\t" "st"#size "a %1, [%2] %%asi\n\t" \
+ "clr %0\n" \
+ "2:\n\n\t" \
+ ".section .fixup,#alloc,#execinstr\n\t" \
+ ".align 4\n" \
+ "3:\n\t" \
+ "sethi %%hi(2b), %0\n\t" \
+ "jmpl %0 + %%lo(2b), %%g0\n\t" \
+ " mov %3, %0\n\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,\"a\"\n\t" \
+ ".align 4\n\t" \
+ ".word 1b, 3b\n\t" \
+ ".previous\n\n\t" \
+ : "=r" (ret) : "r" (x), "r" (__m(addr)), \
+ "i" (-EFAULT))
+
+int __put_user_bad(void);
+
+#define __get_kernel_nofault(dst, src, type, label) \
+do { \
+ type *addr = (type __force *)(src); \
+ register int __gu_ret; \
+ register unsigned long __gu_val; \
+ switch (sizeof(type)) { \
+ case 1: __get_kernel_asm(__gu_val, ub, addr, __gu_ret); break; \
+ case 2: __get_kernel_asm(__gu_val, uh, addr, __gu_ret); break; \
+ case 4: __get_kernel_asm(__gu_val, uw, addr, __gu_ret); break; \
+ case 8: __get_kernel_asm(__gu_val, x, addr, __gu_ret); break; \
+ default: \
+ __gu_val = 0; \
+ __gu_ret = __get_user_bad(); \
+ break; \
+ } \
+ if (__gu_ret) \
+ goto label; \
+ *(type *)dst = (__force type) __gu_val; \
+} while (0)
+#define __get_kernel_asm(x, size, addr, ret) \
+__asm__ __volatile__( \
+ "/* Get kernel asm, inline. */\n" \
+ "1:\t" "ld"#size " [%2], %1\n\t" \
+ "clr %0\n" \
+ "2:\n\n\t" \
+ ".section .fixup,#alloc,#execinstr\n\t" \
+ ".align 4\n" \
+ "3:\n\t" \
+ "sethi %%hi(2b), %0\n\t" \
+ "clr %1\n\t" \
+ "jmpl %0 + %%lo(2b), %%g0\n\t" \
+ " mov %3, %0\n\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,\"a\"\n\t" \
+ ".align 4\n\t" \
+ ".word 1b, 3b\n\n\t" \
+ ".previous\n\t" \
+ : "=r" (ret), "=r" (x) : "r" (__m(addr)), \
+ "i" (-EFAULT))
+
+#define __get_user_nocheck(data, addr, size, type) ({ \
+ register int __gu_ret; \
+ register unsigned long __gu_val; \
+ switch (size) { \
+ case 1: __get_user_asm(__gu_val, ub, addr, __gu_ret); break; \
+ case 2: __get_user_asm(__gu_val, uh, addr, __gu_ret); break; \
+ case 4: __get_user_asm(__gu_val, uw, addr, __gu_ret); break; \
+ case 8: __get_user_asm(__gu_val, x, addr, __gu_ret); break; \
+ default: \
+ __gu_val = 0; \
+ __gu_ret = __get_user_bad(); \
+ break; \
+ } \
+ data = (__force type) __gu_val; \
+ __gu_ret; \
+})
+
+#define __get_user_asm(x, size, addr, ret) \
+__asm__ __volatile__( \
+ "/* Get user asm, inline. */\n" \
+ "1:\t" "ld"#size "a [%2] %%asi, %1\n\t" \
+ "clr %0\n" \
+ "2:\n\n\t" \
+ ".section .fixup,#alloc,#execinstr\n\t" \
+ ".align 4\n" \
+ "3:\n\t" \
+ "sethi %%hi(2b), %0\n\t" \
+ "clr %1\n\t" \
+ "jmpl %0 + %%lo(2b), %%g0\n\t" \
+ " mov %3, %0\n\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table,\"a\"\n\t" \
+ ".align 4\n\t" \
+ ".word 1b, 3b\n\n\t" \
+ ".previous\n\t" \
+ : "=r" (ret), "=r" (x) : "r" (__m(addr)), \
+ "i" (-EFAULT))
+
+int __get_user_bad(void);
+
+unsigned long __must_check raw_copy_from_user(void *to,
+ const void __user *from,
+ unsigned long size);
+
+unsigned long __must_check raw_copy_to_user(void __user *to,
+ const void *from,
+ unsigned long size);
+#define INLINE_COPY_FROM_USER
+#define INLINE_COPY_TO_USER
+
+unsigned long __must_check raw_copy_in_user(void __user *to,
+ const void __user *from,
+ unsigned long size);
+
+unsigned long __must_check __clear_user(void __user *, unsigned long);
+
+#define clear_user __clear_user
+
+__must_check long strnlen_user(const char __user *str, long n);
+
+struct pt_regs;
+unsigned long compute_effective_address(struct pt_regs *,
+ unsigned int insn,
+ unsigned int rd);
+
+#endif /* _ASM_UACCESS_H */
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
new file mode 100644
index 000000000..d6bc76706
--- /dev/null
+++ b/arch/sparc/include/asm/unistd.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * System calls under the Sparc.
+ *
+ * Don't be scared by the ugly clobbers, it is the only way I can
+ * think of right now to force the arguments into fixed registers
+ * before the trap into the system call with gcc 'asm' statements.
+ *
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
+ *
+ * SunOS compatibility based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+#ifndef _SPARC_UNISTD_H
+#define _SPARC_UNISTD_H
+
+#include <uapi/asm/unistd.h>
+
+#define NR_syscalls __NR_syscalls
+
+#ifdef __32bit_syscall_numbers__
+#else
+#define __NR_time 231 /* Linux sparc32 */
+#endif
+#define __ARCH_WANT_NEW_STAT
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME32
+#define __ARCH_WANT_SYS_UTIME32
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#ifdef __32bit_syscall_numbers__
+#define __ARCH_WANT_SYS_IPC
+#else
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_COMPAT_SYS_SENDFILE
+#define __ARCH_WANT_COMPAT_STAT
+#endif
+
+#ifdef __32bit_syscall_numbers__
+/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
+ * it never had the plain ones and there is no value to adding those
+ * old versions into the syscall table.
+ */
+#define __IGNORE_setresuid
+#define __IGNORE_getresuid
+#define __IGNORE_setresgid
+#define __IGNORE_getresgid
+#endif
+
+#endif /* _SPARC_UNISTD_H */
diff --git a/arch/sparc/include/asm/upa.h b/arch/sparc/include/asm/upa.h
new file mode 100644
index 000000000..782691b30
--- /dev/null
+++ b/arch/sparc/include/asm/upa.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_UPA_H
+#define _SPARC64_UPA_H
+
+#include <asm/asi.h>
+
+/* UPA level registers and defines. */
+
+/* UPA Config Register */
+#define UPA_CONFIG_RESV 0xffffffffc0000000 /* Reserved. */
+#define UPA_CONFIG_PCON 0x000000003fc00000 /* Depth of various sys queues. */
+#define UPA_CONFIG_MID 0x00000000003e0000 /* Module ID. */
+#define UPA_CONFIG_PCAP 0x000000000001ffff /* Port Capabilities. */
+
+/* UPA Port ID Register */
+#define UPA_PORTID_FNP 0xff00000000000000 /* Hardcoded to 0xfc on ultra. */
+#define UPA_PORTID_RESV 0x00fffff800000000 /* Reserved. */
+#define UPA_PORTID_ECCVALID 0x0000000400000000 /* Zero if mod can generate ECC */
+#define UPA_PORTID_ONEREAD 0x0000000200000000 /* Set if mod generates P_RASB */
+#define UPA_PORTID_PINTRDQ 0x0000000180000000 /* # outstanding P_INT_REQ's */
+#define UPA_PORTID_PREQDQ 0x000000007e000000 /* slave-wr's to mod supported */
+#define UPA_PORTID_PREQRD 0x0000000001e00000 /* # incoming P_REQ's supported */
+#define UPA_PORTID_UPACAP 0x00000000001f0000 /* UPA capabilities of mod */
+#define UPA_PORTID_ID 0x000000000000ffff /* Module Identification bits */
+
+/* UPA I/O space accessors */
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+static inline unsigned char _upa_readb(unsigned long addr)
+{
+ unsigned char ret;
+
+ __asm__ __volatile__("lduba\t[%1] %2, %0\t/* upa_readb */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+static inline unsigned short _upa_readw(unsigned long addr)
+{
+ unsigned short ret;
+
+ __asm__ __volatile__("lduha\t[%1] %2, %0\t/* upa_readw */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+static inline unsigned int _upa_readl(unsigned long addr)
+{
+ unsigned int ret;
+
+ __asm__ __volatile__("lduwa\t[%1] %2, %0\t/* upa_readl */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+static inline unsigned long _upa_readq(unsigned long addr)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__("ldxa\t[%1] %2, %0\t/* upa_readq */"
+ : "=r" (ret)
+ : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+ return ret;
+}
+
+static inline void _upa_writeb(unsigned char b, unsigned long addr)
+{
+ __asm__ __volatile__("stba\t%0, [%1] %2\t/* upa_writeb */"
+ : /* no outputs */
+ : "r" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _upa_writew(unsigned short w, unsigned long addr)
+{
+ __asm__ __volatile__("stha\t%0, [%1] %2\t/* upa_writew */"
+ : /* no outputs */
+ : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _upa_writel(unsigned int l, unsigned long addr)
+{
+ __asm__ __volatile__("stwa\t%0, [%1] %2\t/* upa_writel */"
+ : /* no outputs */
+ : "r" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+static inline void _upa_writeq(unsigned long q, unsigned long addr)
+{
+ __asm__ __volatile__("stxa\t%0, [%1] %2\t/* upa_writeq */"
+ : /* no outputs */
+ : "r" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define upa_readb(__addr) (_upa_readb((unsigned long)(__addr)))
+#define upa_readw(__addr) (_upa_readw((unsigned long)(__addr)))
+#define upa_readl(__addr) (_upa_readl((unsigned long)(__addr)))
+#define upa_readq(__addr) (_upa_readq((unsigned long)(__addr)))
+#define upa_writeb(__b, __addr) (_upa_writeb((__b), (unsigned long)(__addr)))
+#define upa_writew(__w, __addr) (_upa_writew((__w), (unsigned long)(__addr)))
+#define upa_writel(__l, __addr) (_upa_writel((__l), (unsigned long)(__addr)))
+#define upa_writeq(__q, __addr) (_upa_writeq((__q), (unsigned long)(__addr)))
+#endif /* __KERNEL__ && !__ASSEMBLY__ */
+
+#endif /* !(_SPARC64_UPA_H) */
diff --git a/arch/sparc/include/asm/uprobes.h b/arch/sparc/include/asm/uprobes.h
new file mode 100644
index 000000000..79938fb94
--- /dev/null
+++ b/arch/sparc/include/asm/uprobes.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+/*
+ * User-space Probes (UProbes) for sparc
+ *
+ * Copyright (C) 2013 Oracle, Inc.
+ *
+ * Authors:
+ * Jose E. Marchesi <jose.marchesi@oracle.com>
+ * Eric Saint Etienne <eric.saint.etienne@oracle.com>
+ */
+
+typedef u32 uprobe_opcode_t;
+
+#define MAX_UINSN_BYTES 4
+#define UPROBE_XOL_SLOT_BYTES (MAX_UINSN_BYTES * 2)
+
+#define UPROBE_SWBP_INSN_SIZE 4
+#define UPROBE_SWBP_INSN 0x91d02073 /* ta 0x73 */
+#define UPROBE_STP_INSN 0x91d02074 /* ta 0x74 */
+
+#define ANNUL_BIT (1 << 29)
+
+struct arch_uprobe {
+ union {
+ u8 insn[MAX_UINSN_BYTES];
+ u32 ixol;
+ };
+};
+
+struct arch_uprobe_task {
+ u64 saved_tpc;
+ u64 saved_tnpc;
+};
+
+struct task_struct;
+struct notifier_block;
+
+extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+
+#endif /* _ASM_UPROBES_H */
diff --git a/arch/sparc/include/asm/user.h b/arch/sparc/include/asm/user.h
new file mode 100644
index 000000000..3400ea87f
--- /dev/null
+++ b/arch/sparc/include/asm/user.h
@@ -0,0 +1,6 @@
+#ifndef _SPARC_USER_H
+#define _SPARC_USER_H
+
+/* Nothing to define. */
+
+#endif /* !(_SPARC_USER_H) */
diff --git a/arch/sparc/include/asm/vaddrs.h b/arch/sparc/include/asm/vaddrs.h
new file mode 100644
index 000000000..4fec0341e
--- /dev/null
+++ b/arch/sparc/include/asm/vaddrs.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC_VADDRS_H
+#define _SPARC_VADDRS_H
+
+#include <asm/head.h>
+
+/*
+ * asm/vaddrs.h: Here we define the virtual addresses at
+ * which important things will be mapped.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
+ */
+
+#define SRMMU_MAXMEM 0x0c000000
+
+#define SRMMU_NOCACHE_VADDR (KERNBASE + SRMMU_MAXMEM)
+ /* = 0x0fc000000 */
+/* XXX Empiricals - this needs to go away - KMW */
+#define SRMMU_MIN_NOCACHE_PAGES (550)
+#define SRMMU_MAX_NOCACHE_PAGES (1280)
+
+/* The following constant is used in mm/srmmu.c::srmmu_nocache_calcsize()
+ * to determine the amount of memory that will be reserved as nocache:
+ *
+ * 256 pages will be taken as nocache per each
+ * SRMMU_NOCACHE_ALCRATIO MB of system memory.
+ *
+ * limits enforced: nocache minimum = 256 pages
+ * nocache maximum = 1280 pages
+ */
+#define SRMMU_NOCACHE_ALCRATIO 64 /* 256 pages per 64MB of system RAM */
+
+#ifndef __ASSEMBLY__
+#include <asm/kmap_size.h>
+
+enum fixed_addresses {
+ FIX_HOLE,
+#ifdef CONFIG_HIGHMEM
+ FIX_KMAP_BEGIN,
+ FIX_KMAP_END = (KM_MAX_IDX * NR_CPUS),
+#endif
+ __end_of_fixed_addresses
+};
+#endif
+
+/* Leave one empty page between IO pages at 0xfd000000 and
+ * the top of the fixmap.
+ */
+#define FIXADDR_TOP (0xfcfff000UL)
+#define FIXADDR_SIZE ((FIX_KMAP_END + 1) << PAGE_SHIFT)
+#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
+
+#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+
+#define SUN4M_IOBASE_VADDR 0xfd000000 /* Base for mapping pages */
+#define IOBASE_VADDR 0xfe000000
+#define IOBASE_END 0xfe600000
+
+#define KADB_DEBUGGER_BEGVM 0xffc00000 /* Where kern debugger is in virt-mem */
+#define KADB_DEBUGGER_ENDVM 0xffd00000
+#define DEBUG_FIRSTVADDR KADB_DEBUGGER_BEGVM
+#define DEBUG_LASTVADDR KADB_DEBUGGER_ENDVM
+
+#define LINUX_OPPROM_BEGVM 0xffd00000
+#define LINUX_OPPROM_ENDVM 0xfff00000
+
+#define DVMA_VADDR 0xfff00000 /* Base area of the DVMA on suns */
+#define DVMA_END 0xfffc0000
+
+#endif /* !(_SPARC_VADDRS_H) */
diff --git a/arch/sparc/include/asm/vdso.h b/arch/sparc/include/asm/vdso.h
new file mode 100644
index 000000000..59e79d35c
--- /dev/null
+++ b/arch/sparc/include/asm/vdso.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _ASM_SPARC_VDSO_H
+#define _ASM_SPARC_VDSO_H
+
+struct vdso_image {
+ void *data;
+ unsigned long size; /* Always a multiple of PAGE_SIZE */
+
+ long sym_vvar_start; /* Negative offset to the vvar area */
+};
+
+#ifdef CONFIG_SPARC64
+extern const struct vdso_image vdso_image_64_builtin;
+#endif
+#ifdef CONFIG_COMPAT
+extern const struct vdso_image vdso_image_32_builtin;
+#endif
+
+#endif /* _ASM_SPARC_VDSO_H */
diff --git a/arch/sparc/include/asm/vga.h b/arch/sparc/include/asm/vga.h
new file mode 100644
index 000000000..2952d667d
--- /dev/null
+++ b/arch/sparc/include/asm/vga.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Access to VGA videoram
+ *
+ * (c) 1998 Martin Mares <mj@ucw.cz>
+ */
+
+#ifndef _LINUX_ASM_VGA_H_
+#define _LINUX_ASM_VGA_H_
+
+#include <linux/bug.h>
+#include <linux/string.h>
+#include <asm/types.h>
+
+#define VT_BUF_HAVE_RW
+#define VT_BUF_HAVE_MEMSETW
+#define VT_BUF_HAVE_MEMCPYW
+#define VT_BUF_HAVE_MEMMOVEW
+
+#undef scr_writew
+#undef scr_readw
+
+static inline void scr_writew(u16 val, u16 *addr)
+{
+ BUG_ON((long) addr >= 0);
+
+ *addr = val;
+}
+
+static inline u16 scr_readw(const u16 *addr)
+{
+ BUG_ON((long) addr >= 0);
+
+ return *addr;
+}
+
+static inline void scr_memsetw(u16 *p, u16 v, unsigned int n)
+{
+ BUG_ON((long) p >= 0);
+
+ memset16(p, cpu_to_le16(v), n / 2);
+}
+
+static inline void scr_memcpyw(u16 *d, u16 *s, unsigned int n)
+{
+ BUG_ON((long) d >= 0);
+
+ memcpy(d, s, n);
+}
+
+static inline void scr_memmovew(u16 *d, u16 *s, unsigned int n)
+{
+ BUG_ON((long) d >= 0);
+
+ memmove(d, s, n);
+}
+
+#define VGA_MAP_MEM(x,s) (x)
+
+#endif
diff --git a/arch/sparc/include/asm/viking.h b/arch/sparc/include/asm/viking.h
new file mode 100644
index 000000000..08ffc6050
--- /dev/null
+++ b/arch/sparc/include/asm/viking.h
@@ -0,0 +1,255 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * viking.h: Defines specific to the GNU/Viking MBUS module.
+ * This is SRMMU stuff.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_VIKING_H
+#define _SPARC_VIKING_H
+
+#include <asm/asi.h>
+#include <asm/mxcc.h>
+#include <asm/pgtable.h>
+#include <asm/pgtsrmmu.h>
+
+/* Bits in the SRMMU control register for GNU/Viking modules.
+ *
+ * -----------------------------------------------------------
+ * |impl-vers| RSV |TC|AC|SP|BM|PC|MBM|SB|IC|DC|PSO|RSV|NF|ME|
+ * -----------------------------------------------------------
+ * 31 24 23-17 16 15 14 13 12 11 10 9 8 7 6-2 1 0
+ *
+ * TC: Tablewalk Cacheable -- 0 = Twalks are not cacheable in E-cache
+ * 1 = Twalks are cacheable in E-cache
+ *
+ * GNU/Viking will only cache tablewalks in the E-cache (mxcc) if present
+ * and never caches them internally (or so states the docs). Therefore
+ * for machines lacking an E-cache (ie. in MBUS mode) this bit must
+ * remain cleared.
+ *
+ * AC: Alternate Cacheable -- 0 = Passthru physical accesses not cacheable
+ * 1 = Passthru physical accesses cacheable
+ *
+ * This indicates whether accesses are cacheable when no cachable bit
+ * is present in the pte when the processor is in boot-mode or the
+ * access does not need pte's for translation (ie. pass-thru ASI's).
+ * "Cachable" is only referring to E-cache (if present) and not the
+ * on chip split I/D caches of the GNU/Viking.
+ *
+ * SP: SnooP Enable -- 0 = bus snooping off, 1 = bus snooping on
+ *
+ * This enables snooping on the GNU/Viking bus. This must be on
+ * for the hardware cache consistency mechanisms of the GNU/Viking
+ * to work at all. On non-mxcc GNU/Viking modules the split I/D
+ * caches will snoop regardless of whether they are enabled, this
+ * takes care of the case where the I or D or both caches are turned
+ * off yet still contain valid data. Note also that this bit does
+ * not affect GNU/Viking store-buffer snoops, those happen if the
+ * store-buffer is enabled no matter what.
+ *
+ * BM: Boot Mode -- 0 = not in boot mode, 1 = in boot mode
+ *
+ * This indicates whether the GNU/Viking is in boot-mode or not,
+ * if it is then all instruction fetch physical addresses are
+ * computed as 0xff0000000 + low 28 bits of requested address.
+ * GNU/Viking boot-mode does not affect data accesses. Also,
+ * in boot mode instruction accesses bypass the split on chip I/D
+ * caches, they may be cached by the GNU/MXCC if present and enabled.
+ *
+ * MBM: MBus Mode -- 0 = not in MBus mode, 1 = in MBus mode
+ *
+ * This indicated the GNU/Viking configuration present. If in
+ * MBUS mode, the GNU/Viking lacks a GNU/MXCC E-cache. If it is
+ * not then the GNU/Viking is on a module VBUS connected directly
+ * to a GNU/MXCC cache controller. The GNU/MXCC can be thus connected
+ * to either an GNU/MBUS (sun4m) or the packet-switched GNU/XBus (sun4d).
+ *
+ * SB: StoreBuffer enable -- 0 = store buffer off, 1 = store buffer on
+ *
+ * The GNU/Viking store buffer allows the chip to continue execution
+ * after a store even if the data cannot be placed in one of the
+ * caches during that cycle. If disabled, all stores operations
+ * occur synchronously.
+ *
+ * IC: Instruction Cache -- 0 = off, 1 = on
+ * DC: Data Cache -- 0 = off, 1 = 0n
+ *
+ * These bits enable the on-cpu GNU/Viking split I/D caches. Note,
+ * as mentioned above, these caches will snoop the bus in GNU/MBUS
+ * configurations even when disabled to avoid data corruption.
+ *
+ * NF: No Fault -- 0 = faults generate traps, 1 = faults don't trap
+ * ME: MMU enable -- 0 = mmu not translating, 1 = mmu translating
+ *
+ */
+
+#define VIKING_MMUENABLE 0x00000001
+#define VIKING_NOFAULT 0x00000002
+#define VIKING_PSO 0x00000080
+#define VIKING_DCENABLE 0x00000100 /* Enable data cache */
+#define VIKING_ICENABLE 0x00000200 /* Enable instruction cache */
+#define VIKING_SBENABLE 0x00000400 /* Enable store buffer */
+#define VIKING_MMODE 0x00000800 /* MBUS mode */
+#define VIKING_PCENABLE 0x00001000 /* Enable parity checking */
+#define VIKING_BMODE 0x00002000
+#define VIKING_SPENABLE 0x00004000 /* Enable bus cache snooping */
+#define VIKING_ACENABLE 0x00008000 /* Enable alternate caching */
+#define VIKING_TCENABLE 0x00010000 /* Enable table-walks to be cached */
+#define VIKING_DPENABLE 0x00040000 /* Enable the data prefetcher */
+
+/*
+ * GNU/Viking Breakpoint Action Register fields.
+ */
+#define VIKING_ACTION_MIX 0x00001000 /* Enable multiple instructions */
+
+/*
+ * GNU/Viking Cache Tags.
+ */
+#define VIKING_PTAG_VALID 0x01000000 /* Cache block is valid */
+#define VIKING_PTAG_DIRTY 0x00010000 /* Block has been modified */
+#define VIKING_PTAG_SHARED 0x00000100 /* Shared with some other cache */
+
+#ifndef __ASSEMBLY__
+
+static inline void viking_flush_icache(void)
+{
+ __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"
+ : /* no outputs */
+ : "i" (ASI_M_IC_FLCLEAR)
+ : "memory");
+}
+
+static inline void viking_flush_dcache(void)
+{
+ __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"
+ : /* no outputs */
+ : "i" (ASI_M_DC_FLCLEAR)
+ : "memory");
+}
+
+static inline void viking_unlock_icache(void)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (0x80000000), "i" (ASI_M_IC_FLCLEAR)
+ : "memory");
+}
+
+static inline void viking_unlock_dcache(void)
+{
+ __asm__ __volatile__("sta %%g0, [%0] %1\n\t"
+ : /* no outputs */
+ : "r" (0x80000000), "i" (ASI_M_DC_FLCLEAR)
+ : "memory");
+}
+
+static inline void viking_set_bpreg(unsigned long regval)
+{
+ __asm__ __volatile__("sta %0, [%%g0] %1\n\t"
+ : /* no outputs */
+ : "r" (regval), "i" (ASI_M_ACTION)
+ : "memory");
+}
+
+static inline unsigned long viking_get_bpreg(void)
+{
+ unsigned long regval;
+
+ __asm__ __volatile__("lda [%%g0] %1, %0\n\t"
+ : "=r" (regval)
+ : "i" (ASI_M_ACTION));
+ return regval;
+}
+
+static inline void viking_get_dcache_ptag(int set, int block,
+ unsigned long *data)
+{
+ unsigned long ptag = ((set & 0x7f) << 5) | ((block & 0x3) << 26) |
+ 0x80000000;
+ unsigned long info, page;
+
+ __asm__ __volatile__ ("ldda [%2] %3, %%g2\n\t"
+ "or %%g0, %%g2, %0\n\t"
+ "or %%g0, %%g3, %1\n\t"
+ : "=r" (info), "=r" (page)
+ : "r" (ptag), "i" (ASI_M_DATAC_TAG)
+ : "g2", "g3");
+ data[0] = info;
+ data[1] = page;
+}
+
+static inline void viking_mxcc_turn_off_parity(unsigned long *mregp,
+ unsigned long *mxcc_cregp)
+{
+ unsigned long mreg = *mregp;
+ unsigned long mxcc_creg = *mxcc_cregp;
+
+ mreg &= ~(VIKING_PCENABLE);
+ mxcc_creg &= ~(MXCC_CTL_PARE);
+
+ __asm__ __volatile__ ("set 1f, %%g2\n\t"
+ "andcc %%g2, 4, %%g0\n\t"
+ "bne 2f\n\t"
+ " nop\n"
+ "1:\n\t"
+ "sta %0, [%%g0] %3\n\t"
+ "sta %1, [%2] %4\n\t"
+ "b 1f\n\t"
+ " nop\n\t"
+ "nop\n"
+ "2:\n\t"
+ "sta %0, [%%g0] %3\n\t"
+ "sta %1, [%2] %4\n"
+ "1:\n\t"
+ : /* no output */
+ : "r" (mreg), "r" (mxcc_creg),
+ "r" (MXCC_CREG), "i" (ASI_M_MMUREGS),
+ "i" (ASI_M_MXCC)
+ : "g2", "memory", "cc");
+ *mregp = mreg;
+ *mxcc_cregp = mxcc_creg;
+}
+
+static inline unsigned long viking_hwprobe(unsigned long vaddr)
+{
+ unsigned long val;
+
+ vaddr &= PAGE_MASK;
+ /* Probe all MMU entries. */
+ __asm__ __volatile__("lda [%1] %2, %0\n\t"
+ : "=r" (val)
+ : "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
+ if (!val)
+ return 0;
+
+ /* Probe region. */
+ __asm__ __volatile__("lda [%1] %2, %0\n\t"
+ : "=r" (val)
+ : "r" (vaddr | 0x200), "i" (ASI_M_FLUSH_PROBE));
+ if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) {
+ vaddr &= ~PGDIR_MASK;
+ vaddr >>= PAGE_SHIFT;
+ return val | (vaddr << 8);
+ }
+
+ /* Probe segment. */
+ __asm__ __volatile__("lda [%1] %2, %0\n\t"
+ : "=r" (val)
+ : "r" (vaddr | 0x100), "i" (ASI_M_FLUSH_PROBE));
+ if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) {
+ vaddr &= ~PMD_MASK;
+ vaddr >>= PAGE_SHIFT;
+ return val | (vaddr << 8);
+ }
+
+ /* Probe page. */
+ __asm__ __volatile__("lda [%1] %2, %0\n\t"
+ : "=r" (val)
+ : "r" (vaddr), "i" (ASI_M_FLUSH_PROBE));
+ return val;
+}
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* !(_SPARC_VIKING_H) */
diff --git a/arch/sparc/include/asm/vio.h b/arch/sparc/include/asm/vio.h
new file mode 100644
index 000000000..587fb7841
--- /dev/null
+++ b/arch/sparc/include/asm/vio.h
@@ -0,0 +1,512 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_VIO_H
+#define _SPARC64_VIO_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/list.h>
+#include <linux/log2.h>
+
+#include <asm/ldc.h>
+#include <asm/mdesc.h>
+
+struct vio_msg_tag {
+ u8 type;
+#define VIO_TYPE_CTRL 0x01
+#define VIO_TYPE_DATA 0x02
+#define VIO_TYPE_ERR 0x04
+
+ u8 stype;
+#define VIO_SUBTYPE_INFO 0x01
+#define VIO_SUBTYPE_ACK 0x02
+#define VIO_SUBTYPE_NACK 0x04
+
+ u16 stype_env;
+#define VIO_VER_INFO 0x0001
+#define VIO_ATTR_INFO 0x0002
+#define VIO_DRING_REG 0x0003
+#define VIO_DRING_UNREG 0x0004
+#define VIO_RDX 0x0005
+#define VIO_PKT_DATA 0x0040
+#define VIO_DESC_DATA 0x0041
+#define VIO_DRING_DATA 0x0042
+#define VNET_MCAST_INFO 0x0101
+
+ u32 sid;
+};
+
+struct vio_rdx {
+ struct vio_msg_tag tag;
+ u64 resv[6];
+};
+
+struct vio_ver_info {
+ struct vio_msg_tag tag;
+ u16 major;
+ u16 minor;
+ u8 dev_class;
+#define VDEV_NETWORK 0x01
+#define VDEV_NETWORK_SWITCH 0x02
+#define VDEV_DISK 0x03
+#define VDEV_DISK_SERVER 0x04
+#define VDEV_CONSOLE_CON 0x05
+
+ u8 resv1[3];
+ u64 resv2[5];
+};
+
+struct vio_dring_register {
+ struct vio_msg_tag tag;
+ u64 dring_ident;
+ u32 num_descr;
+ u32 descr_size;
+ u16 options;
+#define VIO_TX_DRING 0x0001
+#define VIO_RX_DRING 0x0002
+#define VIO_RX_DRING_DATA 0x0004
+ u16 resv;
+ u32 num_cookies;
+ struct ldc_trans_cookie cookies[];
+};
+
+struct vio_dring_unregister {
+ struct vio_msg_tag tag;
+ u64 dring_ident;
+ u64 resv[5];
+};
+
+/* Data transfer modes */
+#define VIO_PKT_MODE 0x01 /* Packet based transfer */
+#define VIO_DESC_MODE 0x02 /* In-band descriptors */
+#define VIO_DRING_MODE 0x03 /* Descriptor rings */
+/* in vers >= 1.2, VIO_DRING_MODE is 0x04 and transfer mode is a bitmask */
+#define VIO_NEW_DRING_MODE 0x04
+
+struct vio_dring_data {
+ struct vio_msg_tag tag;
+ u64 seq;
+ u64 dring_ident;
+ u32 start_idx;
+ u32 end_idx;
+ u8 state;
+#define VIO_DRING_ACTIVE 0x01
+#define VIO_DRING_STOPPED 0x02
+
+ u8 __pad1;
+ u16 __pad2;
+ u32 __pad3;
+ u64 __par4[2];
+};
+
+struct vio_dring_hdr {
+ u8 state;
+#define VIO_DESC_FREE 0x01
+#define VIO_DESC_READY 0x02
+#define VIO_DESC_ACCEPTED 0x03
+#define VIO_DESC_DONE 0x04
+ u8 ack;
+#define VIO_ACK_ENABLE 0x01
+#define VIO_ACK_DISABLE 0x00
+
+ u16 __pad1;
+ u32 __pad2;
+};
+
+/* VIO disk specific structures and defines */
+struct vio_disk_attr_info {
+ struct vio_msg_tag tag;
+ u8 xfer_mode;
+ u8 vdisk_type;
+#define VD_DISK_TYPE_SLICE 0x01 /* Slice in block device */
+#define VD_DISK_TYPE_DISK 0x02 /* Entire block device */
+ u8 vdisk_mtype; /* v1.1 */
+#define VD_MEDIA_TYPE_FIXED 0x01 /* Fixed device */
+#define VD_MEDIA_TYPE_CD 0x02 /* CD Device */
+#define VD_MEDIA_TYPE_DVD 0x03 /* DVD Device */
+ u8 resv1;
+ u32 vdisk_block_size;
+ u64 operations;
+ u64 vdisk_size; /* v1.1 */
+ u64 max_xfer_size;
+ u32 phys_block_size; /* v1.2 */
+ u32 resv2;
+ u64 resv3[1];
+};
+
+struct vio_disk_desc {
+ struct vio_dring_hdr hdr;
+ u64 req_id;
+ u8 operation;
+#define VD_OP_BREAD 0x01 /* Block read */
+#define VD_OP_BWRITE 0x02 /* Block write */
+#define VD_OP_FLUSH 0x03 /* Flush disk contents */
+#define VD_OP_GET_WCE 0x04 /* Get write-cache status */
+#define VD_OP_SET_WCE 0x05 /* Enable/disable write-cache */
+#define VD_OP_GET_VTOC 0x06 /* Get VTOC */
+#define VD_OP_SET_VTOC 0x07 /* Set VTOC */
+#define VD_OP_GET_DISKGEOM 0x08 /* Get disk geometry */
+#define VD_OP_SET_DISKGEOM 0x09 /* Set disk geometry */
+#define VD_OP_SCSICMD 0x0a /* SCSI control command */
+#define VD_OP_GET_DEVID 0x0b /* Get device ID */
+#define VD_OP_GET_EFI 0x0c /* Get EFI */
+#define VD_OP_SET_EFI 0x0d /* Set EFI */
+ u8 slice;
+ u16 resv1;
+ u32 status;
+ u64 offset;
+ u64 size;
+ u32 ncookies;
+ u32 resv2;
+ struct ldc_trans_cookie cookies[];
+};
+
+#define VIO_DISK_VNAME_LEN 8
+#define VIO_DISK_ALABEL_LEN 128
+#define VIO_DISK_NUM_PART 8
+
+struct vio_disk_vtoc {
+ u8 volume_name[VIO_DISK_VNAME_LEN];
+ u16 sector_size;
+ u16 num_partitions;
+ u8 ascii_label[VIO_DISK_ALABEL_LEN];
+ struct {
+ u16 id;
+ u16 perm_flags;
+ u32 resv;
+ u64 start_block;
+ u64 num_blocks;
+ } partitions[VIO_DISK_NUM_PART];
+};
+
+struct vio_disk_geom {
+ u16 num_cyl; /* Num data cylinders */
+ u16 alt_cyl; /* Num alternate cylinders */
+ u16 beg_cyl; /* Cyl off of fixed head area */
+ u16 num_hd; /* Num heads */
+ u16 num_sec; /* Num sectors */
+ u16 ifact; /* Interleave factor */
+ u16 apc; /* Alts per cylinder (SCSI) */
+ u16 rpm; /* Revolutions per minute */
+ u16 phy_cyl; /* Num physical cylinders */
+ u16 wr_skip; /* Num sects to skip, writes */
+ u16 rd_skip; /* Num sects to skip, writes */
+};
+
+struct vio_disk_devid {
+ u16 resv;
+ u16 type;
+ u32 len;
+ char id[];
+};
+
+struct vio_disk_efi {
+ u64 lba;
+ u64 len;
+ char data[];
+};
+
+/* VIO net specific structures and defines */
+struct vio_net_attr_info {
+ struct vio_msg_tag tag;
+ u8 xfer_mode;
+ u8 addr_type;
+#define VNET_ADDR_ETHERMAC 0x01
+ u16 ack_freq;
+ u8 plnk_updt;
+#define PHYSLINK_UPDATE_NONE 0x00
+#define PHYSLINK_UPDATE_STATE 0x01
+#define PHYSLINK_UPDATE_STATE_ACK 0x02
+#define PHYSLINK_UPDATE_STATE_NACK 0x03
+ u8 options;
+ u16 resv1;
+ u64 addr;
+ u64 mtu;
+ u16 cflags;
+#define VNET_LSO_IPV4_CAPAB 0x0001
+ u16 ipv4_lso_maxlen;
+ u32 resv2;
+ u64 resv3[2];
+};
+
+#define VNET_NUM_MCAST 7
+
+struct vio_net_mcast_info {
+ struct vio_msg_tag tag;
+ u8 set;
+ u8 count;
+ u8 mcast_addr[VNET_NUM_MCAST * 6];
+ u32 resv;
+};
+
+struct vio_net_desc {
+ struct vio_dring_hdr hdr;
+ u32 size;
+ u32 ncookies;
+ struct ldc_trans_cookie cookies[];
+};
+
+struct vio_net_dext {
+ u8 flags;
+#define VNET_PKT_HASH 0x01
+#define VNET_PKT_HCK_IPV4_HDRCKSUM 0x02
+#define VNET_PKT_HCK_FULLCKSUM 0x04
+#define VNET_PKT_IPV4_LSO 0x08
+#define VNET_PKT_HCK_IPV4_HDRCKSUM_OK 0x10
+#define VNET_PKT_HCK_FULLCKSUM_OK 0x20
+
+ u8 vnet_hashval;
+ u16 ipv4_lso_mss;
+ u32 resv3;
+};
+
+static inline struct vio_net_dext *vio_net_ext(struct vio_net_desc *desc)
+{
+ return (struct vio_net_dext *)&desc->cookies[2];
+}
+
+#define VIO_MAX_RING_COOKIES 24
+
+struct vio_dring_state {
+ u64 ident;
+ void *base;
+ u64 snd_nxt;
+ u64 rcv_nxt;
+ u32 entry_size;
+ u32 num_entries;
+ u32 prod;
+ u32 cons;
+ u32 pending;
+ int ncookies;
+ struct ldc_trans_cookie cookies[VIO_MAX_RING_COOKIES];
+};
+
+#define VIO_TAG_SIZE (sizeof(struct vio_msg_tag))
+#define VIO_VCC_MTU_SIZE (LDC_PACKET_SIZE - VIO_TAG_SIZE)
+
+struct vio_vcc {
+ struct vio_msg_tag tag;
+ char data[VIO_VCC_MTU_SIZE];
+};
+
+static inline void *vio_dring_cur(struct vio_dring_state *dr)
+{
+ return dr->base + (dr->entry_size * dr->prod);
+}
+
+static inline void *vio_dring_entry(struct vio_dring_state *dr,
+ unsigned int index)
+{
+ return dr->base + (dr->entry_size * index);
+}
+
+static inline u32 vio_dring_avail(struct vio_dring_state *dr,
+ unsigned int ring_size)
+{
+ return (dr->pending -
+ ((dr->prod - dr->cons) & (ring_size - 1)) - 1);
+}
+
+static inline u32 vio_dring_next(struct vio_dring_state *dr, u32 index)
+{
+ if (++index == dr->num_entries)
+ index = 0;
+ return index;
+}
+
+static inline u32 vio_dring_prev(struct vio_dring_state *dr, u32 index)
+{
+ if (index == 0)
+ return dr->num_entries - 1;
+ else
+ return index - 1;
+}
+
+#define VIO_MAX_TYPE_LEN 32
+#define VIO_MAX_NAME_LEN 32
+#define VIO_MAX_COMPAT_LEN 64
+
+struct vio_dev {
+ u64 mp;
+ struct device_node *dp;
+
+ char node_name[VIO_MAX_NAME_LEN];
+ char type[VIO_MAX_TYPE_LEN];
+ char compat[VIO_MAX_COMPAT_LEN];
+ int compat_len;
+
+ u64 dev_no;
+
+ unsigned long port_id;
+ unsigned long channel_id;
+
+ unsigned int tx_irq;
+ unsigned int rx_irq;
+ u64 rx_ino;
+ u64 tx_ino;
+
+ /* Handle to the root of "channel-devices" sub-tree in MDESC */
+ u64 cdev_handle;
+
+ /* MD specific data used to identify the vdev in MD */
+ union md_node_info md_node_info;
+
+ struct device dev;
+};
+
+struct vio_driver {
+ const char *name;
+ struct list_head node;
+ const struct vio_device_id *id_table;
+ int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
+ void (*remove)(struct vio_dev *dev);
+ void (*shutdown)(struct vio_dev *dev);
+ unsigned long driver_data;
+ struct device_driver driver;
+ bool no_irq;
+};
+
+struct vio_version {
+ u16 major;
+ u16 minor;
+};
+
+struct vio_driver_state;
+struct vio_driver_ops {
+ int (*send_attr)(struct vio_driver_state *vio);
+ int (*handle_attr)(struct vio_driver_state *vio, void *pkt);
+ void (*handshake_complete)(struct vio_driver_state *vio);
+};
+
+struct vio_completion {
+ struct completion com;
+ int err;
+ int waiting_for;
+};
+
+struct vio_driver_state {
+ /* Protects VIO handshake and, optionally, driver private state. */
+ spinlock_t lock;
+
+ struct ldc_channel *lp;
+
+ u32 _peer_sid;
+ u32 _local_sid;
+ struct vio_dring_state drings[2];
+#define VIO_DRIVER_TX_RING 0
+#define VIO_DRIVER_RX_RING 1
+
+ u8 hs_state;
+#define VIO_HS_INVALID 0x00
+#define VIO_HS_GOTVERS 0x01
+#define VIO_HS_GOT_ATTR 0x04
+#define VIO_HS_SENT_DREG 0x08
+#define VIO_HS_SENT_RDX 0x10
+#define VIO_HS_GOT_RDX_ACK 0x20
+#define VIO_HS_GOT_RDX 0x40
+#define VIO_HS_SENT_RDX_ACK 0x80
+#define VIO_HS_COMPLETE (VIO_HS_GOT_RDX_ACK | VIO_HS_SENT_RDX_ACK)
+
+ u8 dev_class;
+
+ u8 dr_state;
+#define VIO_DR_STATE_TXREG 0x01
+#define VIO_DR_STATE_RXREG 0x02
+#define VIO_DR_STATE_TXREQ 0x10
+#define VIO_DR_STATE_RXREQ 0x20
+
+ u8 debug;
+#define VIO_DEBUG_HS 0x01
+#define VIO_DEBUG_DATA 0x02
+
+ void *desc_buf;
+ unsigned int desc_buf_len;
+
+ struct vio_completion *cmp;
+
+ struct vio_dev *vdev;
+
+ struct timer_list timer;
+
+ struct vio_version ver;
+
+ struct vio_version *ver_table;
+ int ver_table_entries;
+
+ char *name;
+
+ struct vio_driver_ops *ops;
+};
+
+static inline bool vio_version_before(struct vio_driver_state *vio,
+ u16 major, u16 minor)
+{
+ u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
+ u32 want = (u32)major << 16 | minor;
+
+ return have < want;
+}
+
+static inline bool vio_version_after(struct vio_driver_state *vio,
+ u16 major, u16 minor)
+{
+ u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
+ u32 want = (u32)major << 16 | minor;
+
+ return have > want;
+}
+
+static inline bool vio_version_after_eq(struct vio_driver_state *vio,
+ u16 major, u16 minor)
+{
+ u32 have = (u32)vio->ver.major << 16 | vio->ver.minor;
+ u32 want = (u32)major << 16 | minor;
+
+ return have >= want;
+}
+
+#define viodbg(TYPE, f, a...) \
+do { if (vio->debug & VIO_DEBUG_##TYPE) \
+ printk(KERN_INFO "vio: ID[%lu] " f, \
+ vio->vdev->channel_id, ## a); \
+} while (0)
+
+int __vio_register_driver(struct vio_driver *drv, struct module *owner,
+ const char *mod_name);
+/*
+ * vio_register_driver must be a macro so that KBUILD_MODNAME can be expanded
+ */
+#define vio_register_driver(driver) \
+ __vio_register_driver(driver, THIS_MODULE, KBUILD_MODNAME)
+void vio_unregister_driver(struct vio_driver *drv);
+
+static inline struct vio_driver *to_vio_driver(struct device_driver *drv)
+{
+ return container_of(drv, struct vio_driver, driver);
+}
+
+#define to_vio_dev(__dev) container_of_const(__dev, struct vio_dev, dev)
+
+int vio_ldc_send(struct vio_driver_state *vio, void *data, int len);
+void vio_link_state_change(struct vio_driver_state *vio, int event);
+void vio_conn_reset(struct vio_driver_state *vio);
+int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt);
+int vio_validate_sid(struct vio_driver_state *vio,
+ struct vio_msg_tag *tp);
+u32 vio_send_sid(struct vio_driver_state *vio);
+int vio_ldc_alloc(struct vio_driver_state *vio,
+ struct ldc_channel_config *base_cfg, void *event_arg);
+void vio_ldc_free(struct vio_driver_state *vio);
+int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
+ u8 dev_class, struct vio_version *ver_table,
+ int ver_table_size, struct vio_driver_ops *ops,
+ char *name);
+
+void vio_port_up(struct vio_driver_state *vio);
+int vio_set_intr(unsigned long dev_ino, int state);
+u64 vio_vdev_node(struct mdesc_handle *hp, struct vio_dev *vdev);
+
+#endif /* _SPARC64_VIO_H */
diff --git a/arch/sparc/include/asm/visasm.h b/arch/sparc/include/asm/visasm.h
new file mode 100644
index 000000000..7903e84e0
--- /dev/null
+++ b/arch/sparc/include/asm/visasm.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SPARC64_VISASM_H
+#define _SPARC64_VISASM_H
+
+/* visasm.h: FPU saving macros for VIS routines
+ *
+ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#include <asm/pstate.h>
+#include <asm/ptrace.h>
+
+/* Clobbers %o5, %g1, %g2, %g3, %g7, %icc, %xcc */
+
+#define VISEntry \
+ rd %fprs, %o5; \
+ andcc %o5, (FPRS_FEF|FPRS_DU), %g0; \
+ be,pt %icc, 297f; \
+ sethi %hi(297f), %g7; \
+ sethi %hi(VISenter), %g1; \
+ jmpl %g1 + %lo(VISenter), %g0; \
+ or %g7, %lo(297f), %g7; \
+297: wr %g0, FPRS_FEF, %fprs; \
+
+#define VISExit \
+ wr %g0, 0, %fprs;
+
+/* Clobbers %o5, %g1, %g2, %g3, %g7, %icc, %xcc.
+ * Must preserve %o5 between VISEntryHalf and VISExitHalf */
+
+#define VISEntryHalf \
+ VISEntry
+
+#define VISExitHalf \
+ VISExit
+
+#define VISEntryHalfFast(fail_label) \
+ rd %fprs, %o5; \
+ andcc %o5, FPRS_FEF, %g0; \
+ be,pt %icc, 297f; \
+ nop; \
+ ba,a,pt %xcc, fail_label; \
+297: wr %o5, FPRS_FEF, %fprs;
+
+#define VISExitHalfFast \
+ wr %o5, 0, %fprs;
+
+#ifndef __ASSEMBLY__
+static inline void save_and_clear_fpu(void) {
+ __asm__ __volatile__ (
+" rd %%fprs, %%o5\n"
+" andcc %%o5, %0, %%g0\n"
+" be,pt %%icc, 299f\n"
+" sethi %%hi(298f), %%g7\n"
+" sethi %%hi(VISenter), %%g1\n"
+" jmpl %%g1 + %%lo(VISenter), %%g0\n"
+" or %%g7, %%lo(298f), %%g7\n"
+" 298: wr %%g0, 0, %%fprs\n"
+" 299:\n"
+" " : : "i" (FPRS_FEF|FPRS_DU) :
+ "o5", "g1", "g2", "g3", "g7", "cc");
+}
+
+int vis_emul(struct pt_regs *, unsigned int);
+#endif
+
+#endif /* _SPARC64_ASI_H */
diff --git a/arch/sparc/include/asm/vmalloc.h b/arch/sparc/include/asm/vmalloc.h
new file mode 100644
index 000000000..04b8ab951
--- /dev/null
+++ b/arch/sparc/include/asm/vmalloc.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SPARC_VMALLOC_H
+#define _ASM_SPARC_VMALLOC_H
+
+#endif /* _ASM_SPARC_VMALLOC_H */
diff --git a/arch/sparc/include/asm/vvar.h b/arch/sparc/include/asm/vvar.h
new file mode 100644
index 000000000..6eaf5cfca
--- /dev/null
+++ b/arch/sparc/include/asm/vvar.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _ASM_SPARC_VVAR_DATA_H
+#define _ASM_SPARC_VVAR_DATA_H
+
+#include <asm/clocksource.h>
+#include <asm/processor.h>
+#include <asm/barrier.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+struct vvar_data {
+ unsigned int seq;
+
+ int vclock_mode;
+ struct { /* extract of a clocksource struct */
+ u64 cycle_last;
+ u64 mask;
+ int mult;
+ int shift;
+ } clock;
+ /* open coded 'struct timespec' */
+ u64 wall_time_sec;
+ u64 wall_time_snsec;
+ u64 monotonic_time_snsec;
+ u64 monotonic_time_sec;
+ u64 monotonic_time_coarse_sec;
+ u64 monotonic_time_coarse_nsec;
+ u64 wall_time_coarse_sec;
+ u64 wall_time_coarse_nsec;
+
+ int tz_minuteswest;
+ int tz_dsttime;
+};
+
+extern struct vvar_data *vvar_data;
+extern int vdso_fix_stick;
+
+static inline unsigned int vvar_read_begin(const struct vvar_data *s)
+{
+ unsigned int ret;
+
+repeat:
+ ret = READ_ONCE(s->seq);
+ if (unlikely(ret & 1)) {
+ cpu_relax();
+ goto repeat;
+ }
+ smp_rmb(); /* Finish all reads before we return seq */
+ return ret;
+}
+
+static inline int vvar_read_retry(const struct vvar_data *s,
+ unsigned int start)
+{
+ smp_rmb(); /* Finish all reads before checking the value of seq */
+ return unlikely(s->seq != start);
+}
+
+static inline void vvar_write_begin(struct vvar_data *s)
+{
+ ++s->seq;
+ smp_wmb(); /* Makes sure that increment of seq is reflected */
+}
+
+static inline void vvar_write_end(struct vvar_data *s)
+{
+ smp_wmb(); /* Makes the value of seq current before we increment */
+ ++s->seq;
+}
+
+
+#endif /* _ASM_SPARC_VVAR_DATA_H */
diff --git a/arch/sparc/include/asm/winmacro.h b/arch/sparc/include/asm/winmacro.h
new file mode 100644
index 000000000..b6e911f5d
--- /dev/null
+++ b/arch/sparc/include/asm/winmacro.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * winmacro.h: Window loading-unloading macros.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_WINMACRO_H
+#define _SPARC_WINMACRO_H
+
+#include <asm/ptrace.h>
+
+/* Store the register window onto the 8-byte aligned area starting
+ * at %reg. It might be %sp, it might not, we don't care.
+ */
+#define STORE_WINDOW(reg) \
+ std %l0, [%reg + RW_L0]; \
+ std %l2, [%reg + RW_L2]; \
+ std %l4, [%reg + RW_L4]; \
+ std %l6, [%reg + RW_L6]; \
+ std %i0, [%reg + RW_I0]; \
+ std %i2, [%reg + RW_I2]; \
+ std %i4, [%reg + RW_I4]; \
+ std %i6, [%reg + RW_I6];
+
+/* Load a register window from the area beginning at %reg. */
+#define LOAD_WINDOW(reg) \
+ ldd [%reg + RW_L0], %l0; \
+ ldd [%reg + RW_L2], %l2; \
+ ldd [%reg + RW_L4], %l4; \
+ ldd [%reg + RW_L6], %l6; \
+ ldd [%reg + RW_I0], %i0; \
+ ldd [%reg + RW_I2], %i2; \
+ ldd [%reg + RW_I4], %i4; \
+ ldd [%reg + RW_I6], %i6;
+
+/* Loading and storing struct pt_reg trap frames. */
+#define LOAD_PT_INS(base_reg) \
+ ldd [%base_reg + STACKFRAME_SZ + PT_I0], %i0; \
+ ldd [%base_reg + STACKFRAME_SZ + PT_I2], %i2; \
+ ldd [%base_reg + STACKFRAME_SZ + PT_I4], %i4; \
+ ldd [%base_reg + STACKFRAME_SZ + PT_I6], %i6;
+
+#define LOAD_PT_GLOBALS(base_reg) \
+ ld [%base_reg + STACKFRAME_SZ + PT_G1], %g1; \
+ ldd [%base_reg + STACKFRAME_SZ + PT_G2], %g2; \
+ ldd [%base_reg + STACKFRAME_SZ + PT_G4], %g4; \
+ ldd [%base_reg + STACKFRAME_SZ + PT_G6], %g6;
+
+#define LOAD_PT_YREG(base_reg, scratch) \
+ ld [%base_reg + STACKFRAME_SZ + PT_Y], %scratch; \
+ wr %scratch, 0x0, %y;
+
+#define LOAD_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \
+ ld [%base_reg + STACKFRAME_SZ + PT_PSR], %pt_psr; \
+ ld [%base_reg + STACKFRAME_SZ + PT_PC], %pt_pc; \
+ ld [%base_reg + STACKFRAME_SZ + PT_NPC], %pt_npc;
+
+#define LOAD_PT_ALL(base_reg, pt_psr, pt_pc, pt_npc, scratch) \
+ LOAD_PT_YREG(base_reg, scratch) \
+ LOAD_PT_INS(base_reg) \
+ LOAD_PT_GLOBALS(base_reg) \
+ LOAD_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc)
+
+#define STORE_PT_INS(base_reg) \
+ std %i0, [%base_reg + STACKFRAME_SZ + PT_I0]; \
+ std %i2, [%base_reg + STACKFRAME_SZ + PT_I2]; \
+ std %i4, [%base_reg + STACKFRAME_SZ + PT_I4]; \
+ std %i6, [%base_reg + STACKFRAME_SZ + PT_I6];
+
+#define STORE_PT_GLOBALS(base_reg) \
+ st %g1, [%base_reg + STACKFRAME_SZ + PT_G1]; \
+ std %g2, [%base_reg + STACKFRAME_SZ + PT_G2]; \
+ std %g4, [%base_reg + STACKFRAME_SZ + PT_G4]; \
+ std %g6, [%base_reg + STACKFRAME_SZ + PT_G6];
+
+#define STORE_PT_YREG(base_reg, scratch) \
+ rd %y, %scratch; \
+ st %scratch, [%base_reg + STACKFRAME_SZ + PT_Y];
+
+#define STORE_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \
+ st %pt_psr, [%base_reg + STACKFRAME_SZ + PT_PSR]; \
+ st %pt_pc, [%base_reg + STACKFRAME_SZ + PT_PC]; \
+ st %pt_npc, [%base_reg + STACKFRAME_SZ + PT_NPC];
+
+#define STORE_PT_ALL(base_reg, reg_psr, reg_pc, reg_npc, g_scratch) \
+ STORE_PT_PRIV(base_reg, reg_psr, reg_pc, reg_npc) \
+ STORE_PT_GLOBALS(base_reg) \
+ STORE_PT_YREG(base_reg, g_scratch) \
+ STORE_PT_INS(base_reg)
+
+#define SAVE_BOLIXED_USER_STACK(cur_reg, scratch) \
+ ld [%cur_reg + TI_W_SAVED], %scratch; \
+ sll %scratch, 2, %scratch; \
+ add %scratch, %cur_reg, %scratch; \
+ st %sp, [%scratch + TI_RWIN_SPTRS]; \
+ sub %scratch, %cur_reg, %scratch; \
+ sll %scratch, 4, %scratch; \
+ add %scratch, %cur_reg, %scratch; \
+ STORE_WINDOW(scratch + TI_REG_WINDOW); \
+ sub %scratch, %cur_reg, %scratch; \
+ srl %scratch, 6, %scratch; \
+ add %scratch, 1, %scratch; \
+ st %scratch, [%cur_reg + TI_W_SAVED];
+
+#ifdef CONFIG_SMP
+#define LOAD_CURRENT(dest_reg, idreg) \
+661: rd %tbr, %idreg; \
+ srl %idreg, 10, %idreg; \
+ and %idreg, 0xc, %idreg; \
+ .section .cpuid_patch, "ax"; \
+ /* Instruction location. */ \
+ .word 661b; \
+ /* SUN4D implementation. */ \
+ lda [%g0] ASI_M_VIKING_TMP1, %idreg; \
+ sll %idreg, 2, %idreg; \
+ nop; \
+ /* LEON implementation. */ \
+ rd %asr17, %idreg; \
+ srl %idreg, 0x1c, %idreg; \
+ sll %idreg, 0x02, %idreg; \
+ .previous; \
+ sethi %hi(current_set), %dest_reg; \
+ or %dest_reg, %lo(current_set), %dest_reg;\
+ ld [%idreg + %dest_reg], %dest_reg;
+#else
+#define LOAD_CURRENT(dest_reg, idreg) \
+ sethi %hi(current_set), %idreg; \
+ ld [%idreg + %lo(current_set)], %dest_reg;
+#endif
+
+#endif /* !(_SPARC_WINMACRO_H) */
diff --git a/arch/sparc/include/asm/xor.h b/arch/sparc/include/asm/xor.h
new file mode 100644
index 000000000..f4c651e20
--- /dev/null
+++ b/arch/sparc/include/asm/xor.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ___ASM_SPARC_XOR_H
+#define ___ASM_SPARC_XOR_H
+#if defined(__sparc__) && defined(__arch64__)
+#include <asm/xor_64.h>
+#else
+#include <asm/xor_32.h>
+#endif
+#endif
diff --git a/arch/sparc/include/asm/xor_32.h b/arch/sparc/include/asm/xor_32.h
new file mode 100644
index 000000000..0351813cf
--- /dev/null
+++ b/arch/sparc/include/asm/xor_32.h
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * include/asm/xor.h
+ *
+ * Optimized RAID-5 checksumming functions for 32-bit Sparc.
+ */
+
+/*
+ * High speed xor_block operation for RAID4/5 utilizing the
+ * ldd/std SPARC instructions.
+ *
+ * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+static void
+sparc_2(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2)
+{
+ int lines = bytes / (sizeof (long)) / 8;
+
+ do {
+ __asm__ __volatile__(
+ "ldd [%0 + 0x00], %%g2\n\t"
+ "ldd [%0 + 0x08], %%g4\n\t"
+ "ldd [%0 + 0x10], %%o0\n\t"
+ "ldd [%0 + 0x18], %%o2\n\t"
+ "ldd [%1 + 0x00], %%o4\n\t"
+ "ldd [%1 + 0x08], %%l0\n\t"
+ "ldd [%1 + 0x10], %%l2\n\t"
+ "ldd [%1 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "std %%g2, [%0 + 0x00]\n\t"
+ "std %%g4, [%0 + 0x08]\n\t"
+ "std %%o0, [%0 + 0x10]\n\t"
+ "std %%o2, [%0 + 0x18]\n"
+ :
+ : "r" (p1), "r" (p2)
+ : "g2", "g3", "g4", "g5",
+ "o0", "o1", "o2", "o3", "o4", "o5",
+ "l0", "l1", "l2", "l3", "l4", "l5");
+ p1 += 8;
+ p2 += 8;
+ } while (--lines > 0);
+}
+
+static void
+sparc_3(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3)
+{
+ int lines = bytes / (sizeof (long)) / 8;
+
+ do {
+ __asm__ __volatile__(
+ "ldd [%0 + 0x00], %%g2\n\t"
+ "ldd [%0 + 0x08], %%g4\n\t"
+ "ldd [%0 + 0x10], %%o0\n\t"
+ "ldd [%0 + 0x18], %%o2\n\t"
+ "ldd [%1 + 0x00], %%o4\n\t"
+ "ldd [%1 + 0x08], %%l0\n\t"
+ "ldd [%1 + 0x10], %%l2\n\t"
+ "ldd [%1 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "ldd [%2 + 0x00], %%o4\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "ldd [%2 + 0x08], %%l0\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "ldd [%2 + 0x10], %%l2\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "ldd [%2 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "std %%g2, [%0 + 0x00]\n\t"
+ "std %%g4, [%0 + 0x08]\n\t"
+ "std %%o0, [%0 + 0x10]\n\t"
+ "std %%o2, [%0 + 0x18]\n"
+ :
+ : "r" (p1), "r" (p2), "r" (p3)
+ : "g2", "g3", "g4", "g5",
+ "o0", "o1", "o2", "o3", "o4", "o5",
+ "l0", "l1", "l2", "l3", "l4", "l5");
+ p1 += 8;
+ p2 += 8;
+ p3 += 8;
+ } while (--lines > 0);
+}
+
+static void
+sparc_4(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3,
+ const unsigned long * __restrict p4)
+{
+ int lines = bytes / (sizeof (long)) / 8;
+
+ do {
+ __asm__ __volatile__(
+ "ldd [%0 + 0x00], %%g2\n\t"
+ "ldd [%0 + 0x08], %%g4\n\t"
+ "ldd [%0 + 0x10], %%o0\n\t"
+ "ldd [%0 + 0x18], %%o2\n\t"
+ "ldd [%1 + 0x00], %%o4\n\t"
+ "ldd [%1 + 0x08], %%l0\n\t"
+ "ldd [%1 + 0x10], %%l2\n\t"
+ "ldd [%1 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "ldd [%2 + 0x00], %%o4\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "ldd [%2 + 0x08], %%l0\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "ldd [%2 + 0x10], %%l2\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "ldd [%2 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "ldd [%3 + 0x00], %%o4\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "ldd [%3 + 0x08], %%l0\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "ldd [%3 + 0x10], %%l2\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "ldd [%3 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "std %%g2, [%0 + 0x00]\n\t"
+ "std %%g4, [%0 + 0x08]\n\t"
+ "std %%o0, [%0 + 0x10]\n\t"
+ "std %%o2, [%0 + 0x18]\n"
+ :
+ : "r" (p1), "r" (p2), "r" (p3), "r" (p4)
+ : "g2", "g3", "g4", "g5",
+ "o0", "o1", "o2", "o3", "o4", "o5",
+ "l0", "l1", "l2", "l3", "l4", "l5");
+ p1 += 8;
+ p2 += 8;
+ p3 += 8;
+ p4 += 8;
+ } while (--lines > 0);
+}
+
+static void
+sparc_5(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3,
+ const unsigned long * __restrict p4,
+ const unsigned long * __restrict p5)
+{
+ int lines = bytes / (sizeof (long)) / 8;
+
+ do {
+ __asm__ __volatile__(
+ "ldd [%0 + 0x00], %%g2\n\t"
+ "ldd [%0 + 0x08], %%g4\n\t"
+ "ldd [%0 + 0x10], %%o0\n\t"
+ "ldd [%0 + 0x18], %%o2\n\t"
+ "ldd [%1 + 0x00], %%o4\n\t"
+ "ldd [%1 + 0x08], %%l0\n\t"
+ "ldd [%1 + 0x10], %%l2\n\t"
+ "ldd [%1 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "ldd [%2 + 0x00], %%o4\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "ldd [%2 + 0x08], %%l0\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "ldd [%2 + 0x10], %%l2\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "ldd [%2 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "ldd [%3 + 0x00], %%o4\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "ldd [%3 + 0x08], %%l0\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "ldd [%3 + 0x10], %%l2\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "ldd [%3 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "ldd [%4 + 0x00], %%o4\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "ldd [%4 + 0x08], %%l0\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "ldd [%4 + 0x10], %%l2\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "ldd [%4 + 0x18], %%l4\n\t"
+ "xor %%g2, %%o4, %%g2\n\t"
+ "xor %%g3, %%o5, %%g3\n\t"
+ "xor %%g4, %%l0, %%g4\n\t"
+ "xor %%g5, %%l1, %%g5\n\t"
+ "xor %%o0, %%l2, %%o0\n\t"
+ "xor %%o1, %%l3, %%o1\n\t"
+ "xor %%o2, %%l4, %%o2\n\t"
+ "xor %%o3, %%l5, %%o3\n\t"
+ "std %%g2, [%0 + 0x00]\n\t"
+ "std %%g4, [%0 + 0x08]\n\t"
+ "std %%o0, [%0 + 0x10]\n\t"
+ "std %%o2, [%0 + 0x18]\n"
+ :
+ : "r" (p1), "r" (p2), "r" (p3), "r" (p4), "r" (p5)
+ : "g2", "g3", "g4", "g5",
+ "o0", "o1", "o2", "o3", "o4", "o5",
+ "l0", "l1", "l2", "l3", "l4", "l5");
+ p1 += 8;
+ p2 += 8;
+ p3 += 8;
+ p4 += 8;
+ p5 += 8;
+ } while (--lines > 0);
+}
+
+static struct xor_block_template xor_block_SPARC = {
+ .name = "SPARC",
+ .do_2 = sparc_2,
+ .do_3 = sparc_3,
+ .do_4 = sparc_4,
+ .do_5 = sparc_5,
+};
+
+/* For grins, also test the generic routines. */
+#include <asm-generic/xor.h>
+
+#undef XOR_TRY_TEMPLATES
+#define XOR_TRY_TEMPLATES \
+ do { \
+ xor_speed(&xor_block_8regs); \
+ xor_speed(&xor_block_32regs); \
+ xor_speed(&xor_block_SPARC); \
+ } while (0)
diff --git a/arch/sparc/include/asm/xor_64.h b/arch/sparc/include/asm/xor_64.h
new file mode 100644
index 000000000..caaddea8a
--- /dev/null
+++ b/arch/sparc/include/asm/xor_64.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * include/asm/xor.h
+ *
+ * High speed xor_block operation for RAID4/5 utilizing the
+ * UltraSparc Visual Instruction Set and Niagara block-init
+ * twin-load instructions.
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 2006 David S. Miller <davem@davemloft.net>
+ */
+
+#include <asm/spitfire.h>
+
+void xor_vis_2(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2);
+void xor_vis_3(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3);
+void xor_vis_4(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3,
+ const unsigned long * __restrict p4);
+void xor_vis_5(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3,
+ const unsigned long * __restrict p4,
+ const unsigned long * __restrict p5);
+
+/* XXX Ugh, write cheetah versions... -DaveM */
+
+static struct xor_block_template xor_block_VIS = {
+ .name = "VIS",
+ .do_2 = xor_vis_2,
+ .do_3 = xor_vis_3,
+ .do_4 = xor_vis_4,
+ .do_5 = xor_vis_5,
+};
+
+void xor_niagara_2(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2);
+void xor_niagara_3(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3);
+void xor_niagara_4(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3,
+ const unsigned long * __restrict p4);
+void xor_niagara_5(unsigned long bytes, unsigned long * __restrict p1,
+ const unsigned long * __restrict p2,
+ const unsigned long * __restrict p3,
+ const unsigned long * __restrict p4,
+ const unsigned long * __restrict p5);
+
+static struct xor_block_template xor_block_niagara = {
+ .name = "Niagara",
+ .do_2 = xor_niagara_2,
+ .do_3 = xor_niagara_3,
+ .do_4 = xor_niagara_4,
+ .do_5 = xor_niagara_5,
+};
+
+#undef XOR_TRY_TEMPLATES
+#define XOR_TRY_TEMPLATES \
+ do { \
+ xor_speed(&xor_block_VIS); \
+ xor_speed(&xor_block_niagara); \
+ } while (0)
+
+/* For VIS for everything except Niagara. */
+#define XOR_SELECT_TEMPLATE(FASTEST) \
+ ((tlb_type == hypervisor && \
+ (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA3 || \
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA4 || \
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA5)) ? \
+ &xor_block_niagara : \
+ &xor_block_VIS)