code:
// SPDX-License-Identifier: GPL-2.0
/*
 *	linux/arch/alpha/kernel/pci_iommu.c
 */

#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/pci.h>
#include <linux/gfp.h>
#include <linux/memblock.h>
#include <linux/export.h>
#include <linux/scatterlist.h>
#include <linux/log2.h>
#include <linux/dma-map-ops.h>
#include <linux/iommu-helper.h>

#include <asm/io.h>
#include <asm/hwrpb.h>

#include "proto.h"
#include "pci_impl.h"

#define DEBUG_ALLOC 0
#if DEBUG_ALLOC > 0
# define DBGA(args...)		printk(KERN_DEBUG args)
#else
# define DBGA(args...)
#endif
#if DEBUG_ALLOC > 1
# define DBGA2(args...)		printk(KERN_DEBUG args)
#else
# define DBGA2(args...)
#endif

#define DEBUG_NODIRECT 0

#define ISA_DMA_MASK		0x00ffffff

static inline unsigned long
mk_iommu_pte(unsigned long paddr)
{
	return (paddr >> (PAGE_SHIFT-1)) | 1;
}

/* Return the minimum of MAX or the first power of two larger
   than main memory.  */

unsigned long
size_for_memory(unsigned long max)
{
	unsigned long mem = max_low_pfn << PAGE_SHIFT;
	if (mem < max)
		max = roundup_pow_of_two(mem);
	return max;
}

struct pci_iommu_arena * __init
iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base,
		     unsigned long window_size, unsigned long align)
{
	unsigned long mem_size;
	struct pci_iommu_arena *arena;

	mem_size = window_size / (PAGE_SIZE / sizeof(unsigned long));

	/* Note that the TLB lookup logic uses bitwise concatenation,
	   not addition, so the required arena alignment is based on
	   the size of the window.  Retain the align parameter so that
	   particular systems can over-align the arena.  */
	if (align < mem_size)
		align = mem_size;

	arena = memblock_alloc(sizeof(*arena), SMP_CACHE_BYTES);
	if (!arena)
		panic("%s: Failed to allocate %zu bytes\n", __func__,
		      sizeof(*arena));
	arena->ptes = memblock_alloc(mem_size, align);
	if (!arena->ptes)
		panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
		      __func__, mem_size, align);

	spin_lock_init(&arena->lock);
	arena->hose = hose;
	arena->dma_base = base;
	arena->size = window_size;
	arena->next_entry = 0;

	/* Align allocations to a multiple of a page size.  Not needed
	   unless there are chip bugs.  */
	arena->align_entry = 1;

	return arena;
}

struct pci_iommu_arena * __init
iommu_arena_new(struct pci_controller *hose, dma_addr_t base,
		unsigned long window_size, unsigned long align)
{
	return iommu_arena_new_node(0, hose, base, window_size, align);
}

/* Must be called with the arena lock held */
static long
iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
		       long n, long mask)
{
	unsigned long *ptes;
	long i, p, nent;
	int pass = 0;
	unsigned long base;
	unsigned long boundary_size;

	base = arena->dma_base >> PAGE_SHIFT;
	boundary_size = dma_get_seg_boundary_nr_pages(dev, PAGE_SHIFT);

	/* Search forward for the first mask-aligned sequence of N free ptes */
	ptes = arena->ptes;
	nent = arena->size >> PAGE_SHIFT;
	p = ALIGN(arena->next_entry, mask + 1);
	i = 0;

again:
	while (i < n && p+i < nent) {
		if (!i && iommu_is_span_boundary(p, n, base, boundary_size)) {
			p = ALIGN(p + 1, mask + 1);
			goto again;
		}

		if (ptes[p+i])
			p = ALIGN(p + i + 1, mask + 1), i = 0;
		else
			i = i + 1;
	}

	if (i < n) {
		if (pass < 1) {
			/*
			 * Reached the end.  Flush the TLB and restart
			 * the search from the beginning.
			*/
			alpha_mv.mv_pci_tbi(arena->hose, 0, -1);

			pass++;
			p = 0;
			i = 0;
			goto again;
		} else
			return -1;
	}

	/* Success. It's the responsibility of the caller to mark them
	   in use before releasing the lock */
	return p;
}

static long
iommu_arena_alloc(struct device *dev, struct pci_iommu_arena *arena, long n,
		  unsigned int align)
{
	unsigned long flags;
	unsigned long *ptes;
	long i, p, mask;

	spin_lock_irqsave(&arena->lock, flags);

	/* Search for N empty ptes */
	ptes = arena->ptes;
	mask = max(align, arena->align_entry) - 1;
	p = iommu_arena_find_pages(dev, arena, n, mask);
	if (p < 0) {
		spin_unlock_irqrestore(&arena->lock, flags);
		return -1;
	}

	/* Success.  Mark them all in use, ie not zero and invalid
	   for the iommu tlb that could load them from under us.
	   The chip specific bits will fill this in with something
	   kosher when we return.  */
	for (i = 0; i < n; ++i)
		ptes[p+i] = IOMMU_INVALID_PTE;

	arena->next_entry = p + n;
	spin_unlock_irqrestore(&arena->lock, flags);

	return p;
}

static void
iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
{
	unsigned long *p;
	long i;

	p = arena->ptes + ofs;
	for (i = 0; i < n; ++i)
		p[i] = 0;
}

/*
 * True if the machine supports DAC addressing, and DEV can
 * make use of it given MASK.
 */
static int pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
{
	dma_addr_t dac_offset = alpha_mv.pci_dac_offset;
	int ok = 1;

	/* If this is not set, the machine doesn't support DAC at all.  */
	if (dac_offset == 0)
		ok = 0;

	/* The device has to be able to address our DAC bit.  */
	if ((dac_offset & dev->dma_mask) != dac_offset)
		ok = 0;

	/* If both conditions above are met, we are fine. */
	DBGA("pci_dac_dma_supported %s from %ps\n",
	     ok ? "yes" : "no", __builtin_return_address(0));

	return ok;
}

/* Map a single buffer of the indicated size for PCI DMA in streaming
   mode.  The 32-bit PCI bus mastering address to use is returned.
   Once the device is given the dma address, the device owns this memory
   until either pci_unmap_single or pci_dma_sync_single is performed.  */

static dma_addr_t
pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
		 int dac_allowed)
{
	struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
	dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
	struct pci_iommu_arena *arena;
	long npages, dma_ofs, i;
	unsigned long paddr;
	dma_addr_t ret;
	unsigned int align = 0;
	struct device *dev = pdev ? &pdev->dev : NULL;

	paddr = __pa(cpu_addr);

#if !DEBUG_NODIRECT
	/* First check to see if we can use the direct map window.  */
	if (paddr + size + __direct_map_base - 1 <= max_dma
	    && paddr + size <= __direct_map_size) {
		ret = paddr + __direct_map_base;

		DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %ps\n",
		      cpu_addr, size, ret, __builtin_return_address(0));

		return ret;
	}
#endif

	/* Next, use DAC if selected earlier.  */
	if (dac_allowed) {
		ret = paddr + alpha_mv.pci_dac_offset;

		DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %ps\n",
		      cpu_addr, size, ret, __builtin_return_address(0));

		return ret;
	}

	/* If the machine doesn't define a pci_tbi routine, we have to
	   assume it doesn't support sg mapping, and, since we tried to
	   use direct_map above, it now must be considered an error. */
	if (! alpha_mv.mv_pci_tbi) {
		printk_once(KERN_WARNING "pci_map_single: no HW sg\n");
		return DMA_MAPPING_ERROR;
	}

	arena = hose->sg_pci;
	if (!arena || arena->dma_base + arena->size - 1 > max_dma)
		arena = hose->sg_isa;

	npages = iommu_num_pages(paddr, size, PAGE_SIZE);

	/* Force allocation to 64KB boundary for ISA bridges. */
	if (pdev && pdev == isa_bridge)
		align = 8;
	dma_ofs = iommu_arena_alloc(dev, arena, npages, align);
	if (dma_ofs < 0) {
		printk(KERN_WARNING "pci_map_single failed: "
		       "could not allocate dma page tables\n");
		return DMA_MAPPING_ERROR;
	}

	paddr &= PAGE_MASK;
	for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
		arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);

	ret = arena->dma_base + dma_ofs * PAGE_SIZE;
	ret += (unsigned long)cpu_addr & ~PAGE_MASK;

	DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %ps\n",
	      cpu_addr, size, npages, ret, __builtin_return_address(0));

	return ret;
}

/* Helper for generic DMA-mapping functions. */
static struct pci_dev *alpha_gendev_to_pci(struct device *dev)
{
	if (dev && dev_is_pci(dev))
		return to_pci_dev(dev);

	/* Assume that non-PCI devices asking for DMA are either ISA or EISA,
	   BUG() otherwise. */
	BUG_ON(!isa_bridge);

	/* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
	   bridge is bus master then). */
	if (!dev || !dev->dma_mask || !*dev->dma_mask)
		return isa_bridge;

	/* For EISA bus masters, return isa_bridge (it might have smaller
	   dma_mask due to wiring limitations). */
	if (*dev->dma_mask >= isa_bridge->dma_mask)
		return isa_bridge;

	/* This assumes ISA bus master with dma_mask 0xffffff. */
	return NULL;
}

static dma_addr_t alpha_pci_map_page(struct device *dev, struct page *page,
				     unsigned long offset, size_t size,
				     enum dma_data_direction dir,
				     unsigned long attrs)
{
	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
	int dac_allowed;

	BUG_ON(dir == DMA_NONE);

	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
	return pci_map_single_1(pdev, (char *)page_address(page) + offset,
				size, dac_allowed);
}

/* Unmap a single streaming mode DMA translation.  The DMA_ADDR and
   SIZE must match what was provided for in a previous pci_map_single
   call.  All other usages are undefined.  After this call, reads by
   the cpu to the buffer are guaranteed to see whatever the device
   wrote there.  */

static void alpha_pci_unmap_page(struct device *dev, dma_addr_t dma_addr,
				 size_t size, enum dma_data_direction dir,
				 unsigned long attrs)
{
	unsigned long flags;
	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
	struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
	struct pci_iommu_arena *arena;
	long dma_ofs, npages;

	BUG_ON(dir == DMA_NONE);

	if (dma_addr >= __direct_map_base
	    && dma_addr < __direct_map_base + __direct_map_size) {
		/* Nothing to do.  */

		DBGA2("pci_unmap_single: direct [%llx,%zx] from %ps\n",
		      dma_addr, size, __builtin_return_address(0));

		return;
	}

	if (dma_addr > 0xffffffff) {
		DBGA2("pci64_unmap_single: DAC [%llx,%zx] from %ps\n",
		      dma_addr, size, __builtin_return_address(0));
		return;
	}

	arena = hose->sg_pci;
	if (!arena || dma_addr < arena->dma_base)
		arena = hose->sg_isa;

	dma_ofs = (dma_addr - arena->dma_base) >> PAGE_SHIFT;
	if (dma_ofs * PAGE_SIZE >= arena->size) {
		printk(KERN_ERR "Bogus pci_unmap_single: dma_addr %llx "
		       " base %llx size %x\n",
		       dma_addr, arena->dma_base, arena->size);
		return;
		BUG();
	}

	npages = iommu_num_pages(dma_addr, size, PAGE_SIZE);

	spin_lock_irqsave(&arena->lock, flags);

	iommu_arena_free(arena, dma_ofs, npages);

        /* If we're freeing ptes above the `next_entry' pointer (they
           may have snuck back into the TLB since the last wrap flush),
           we need to flush the TLB before reallocating the latter.  */
	if (dma_ofs >= arena->next_entry)
		alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1);

	spin_unlock_irqrestore(&arena->lock, flags);

	DBGA2("pci_unmap_single: sg [%llx,%zx] np %ld from %ps\n",
	      dma_addr, size, npages, __builtin_return_address(0));
}

/* Allocate and map kernel buffer using consistent mode DMA for PCI
   device.  Returns non-NULL cpu-view pointer to the buffer if
   successful and sets *DMA_ADDRP to the pci side dma address as well,
   else DMA_ADDRP is undefined.  */

static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
				      dma_addr_t *dma_addrp, gfp_t gfp,
				      unsigned long attrs)
{
	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
	void *cpu_addr;
	long order = get_order(size);

	gfp &= ~GFP_DMA;

try_again:
	cpu_addr = (void *)__get_free_pages(gfp | __GFP_ZERO, order);
	if (! cpu_addr) {
		printk(KERN_INFO "pci_alloc_consistent: "
		       "get_free_pages failed from %ps\n",
			__builtin_return_address(0));
		/* ??? Really atomic allocation?  Otherwise we could play
		   with vmalloc and sg if we can't find contiguous memory.  */
		return NULL;
	}
	memset(cpu_addr, 0, size);

	*dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
	if (*dma_addrp == DMA_MAPPING_ERROR) {
		free_pages((unsigned long)cpu_addr, order);
		if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
			return NULL;
		/* The address doesn't fit required mask and we
		   do not have iommu. Try again with GFP_DMA. */
		gfp |= GFP_DMA;
		goto try_again;
	}

	DBGA2("pci_alloc_consistent: %zx -> [%p,%llx] from %ps\n",
	      size, cpu_addr, *dma_addrp, __builtin_return_address(0));

	return cpu_addr;
}

/* Free and unmap a consistent DMA buffer.  CPU_ADDR and DMA_ADDR must
   be values that were returned from pci_alloc_consistent.  SIZE must
   be the same as what as passed into pci_alloc_consistent.
   References to the memory and mappings associated with CPU_ADDR or
   DMA_ADDR past this call are illegal.  */

static void alpha_pci_free_coherent(struct device *dev, size_t size,
				    void *cpu_addr, dma_addr_t dma_addr,
				    unsigned long attrs)
{
	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
	dma_unmap_single(&pdev->dev, dma_addr, size, DMA_BIDIRECTIONAL);
	free_pages((unsigned long)cpu_addr, get_order(size));

	DBGA2("pci_free_consistent: [%llx,%zx] from %ps\n",
	      dma_addr, size, __builtin_return_address(0));
}

/* Classify the elements of the scatterlist.  Write dma_address
   of each element with:
	0   : Followers all physically adjacent.
	1   : Followers all virtually adjacent.
	-1  : Not leader, physically adjacent to previous.
	-2  : Not leader, virtually adjacent to previous.
   Write dma_length of each leader with the combined lengths of
   the mergable followers.  */

#define SG_ENT_VIRT_ADDRESS(SG) (sg_virt((SG)))
#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))

static void
sg_classify(struct device *dev, struct scatterlist *sg, struct scatterlist *end,
	    int virt_ok)
{
	unsigned long next_paddr;
	struct scatterlist *leader;
	long leader_flag, leader_length;
	unsigned int max_seg_size;

	leader = sg;
	leader_flag = 0;
	leader_length = leader->length;
	next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;

	/* we will not marge sg without device. */
	max_seg_size = dev ? dma_get_max_seg_size(dev) : 0;
	for (++sg; sg < end; ++sg) {
		unsigned long addr, len;
		addr = SG_ENT_PHYS_ADDRESS(sg);
		len = sg->length;

		if (leader_length + len > max_seg_size)
			goto new_segment;

		if (next_paddr == addr) {
			sg->dma_address = -1;
			leader_length += len;
		} else if (((next_paddr | addr) & ~PAGE_MASK) == 0 && virt_ok) {
			sg->dma_address = -2;
			leader_flag = 1;
			leader_length += len;
		} else {
new_segment:
			leader->dma_address = leader_flag;
			leader->dma_length = leader_length;
			leader = sg;
			leader_flag = 0;
			leader_length = len;
		}

		next_paddr = addr + len;
	}

	leader->dma_address = leader_flag;
	leader->dma_length = leader_length;
}

/* Given a scatterlist leader, choose an allocation method and fill
   in the blanks.  */

static int
sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
	struct scatterlist *out, struct pci_iommu_arena *arena,
	dma_addr_t max_dma, int dac_allowed)
{
	unsigned long paddr = SG_ENT_PHYS_ADDRESS(leader);
	long size = leader->dma_length;
	struct scatterlist *sg;
	unsigned long *ptes;
	long npages, dma_ofs, i;

#if !DEBUG_NODIRECT
	/* If everything is physically contiguous, and the addresses
	   fall into the direct-map window, use it.  */
	if (leader->dma_address == 0
	    && paddr + size + __direct_map_base - 1 <= max_dma
	    && paddr + size <= __direct_map_size) {
		out->dma_address = paddr + __direct_map_base;
		out->dma_length = size;

		DBGA("    sg_fill: [%p,%lx] -> direct %llx\n",
		     __va(paddr), size, out->dma_address);

		return 0;
	}
#endif

	/* If physically contiguous and DAC is available, use it.  */
	if (leader->dma_address == 0 && dac_allowed) {
		out->dma_address = paddr + alpha_mv.pci_dac_offset;
		out->dma_length = size;

		DBGA("    sg_fill: [%p,%lx] -> DAC %llx\n",
		     __va(paddr), size, out->dma_address);

		return 0;
	}

	/* Otherwise, we'll use the iommu to make the pages virtually
	   contiguous.  */

	paddr &= ~PAGE_MASK;
	npages = iommu_num_pages(paddr, size, PAGE_SIZE);
	dma_ofs = iommu_arena_alloc(dev, arena, npages, 0);
	if (dma_ofs < 0) {
		/* If we attempted a direct map above but failed, die.  */
		if (leader->dma_address == 0)
			return -1;

		/* Otherwise, break up the remaining virtually contiguous
		   hunks into individual direct maps and retry.  */
		sg_classify(dev, leader, end, 0);
		return sg_fill(dev, leader, end, out, arena, max_dma, dac_allowed);
	}

	out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
	out->dma_length = size;

	DBGA("    sg_fill: [%p,%lx] -> sg %llx np %ld\n",
	     __va(paddr), size, out->dma_address, npages);

	/* All virtually contiguous.  We need to find the length of each
	   physically contiguous subsegment to fill in the ptes.  */
	ptes = &arena->ptes[dma_ofs];
	sg = leader;
	do {
#if DEBUG_ALLOC > 0
		struct scatterlist *last_sg = sg;
#endif

		size = sg->length;
		paddr = SG_ENT_PHYS_ADDRESS(sg);

		while (sg+1 < end && (int) sg[1].dma_address == -1) {
			size += sg[1].length;
			sg = sg_next(sg);
		}

		npages = iommu_num_pages(paddr, size, PAGE_SIZE);

		paddr &= PAGE_MASK;
		for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
			*ptes++ = mk_iommu_pte(paddr);

#if DEBUG_ALLOC > 0
		DBGA("    (%ld) [%p,%x] np %ld\n",
		     last_sg - leader, SG_ENT_VIRT_ADDRESS(last_sg),
		     last_sg->length, npages);
		while (++last_sg <= sg) {
			DBGA("        (%ld) [%p,%x] cont\n",
			     last_sg - leader, SG_ENT_VIRT_ADDRESS(last_sg),
			     last_sg->length);
		}
#endif
	} while (++sg < end && (int) sg->dma_address < 0);

	return 1;
}

static int alpha_pci_map_sg(struct device *dev, struct scatterlist *sg,
			    int nents, enum dma_data_direction dir,
			    unsigned long attrs)
{
	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
	struct scatterlist *start, *end, *out;
	struct pci_controller *hose;
	struct pci_iommu_arena *arena;
	dma_addr_t max_dma;
	int dac_allowed;

	BUG_ON(dir == DMA_NONE);

	dac_allowed = dev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;

	/* Fast path single entry scatterlists.  */
	if (nents == 1) {
		sg->dma_length = sg->length;
		sg->dma_address
		  = pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg),
				     sg->length, dac_allowed);
		if (sg->dma_address == DMA_MAPPING_ERROR)
			return -EIO;
		return 1;
	}

	start = sg;
	end = sg + nents;

	/* First, prepare information about the entries.  */
	sg_classify(dev, sg, end, alpha_mv.mv_pci_tbi != 0);

	/* Second, figure out where we're going to map things.  */
	if (alpha_mv.mv_pci_tbi) {
		hose = pdev ? pdev->sysdata : pci_isa_hose;
		max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
		arena = hose->sg_pci;
		if (!arena || arena->dma_base + arena->size - 1 > max_dma)
			arena = hose->sg_isa;
	} else {
		max_dma = -1;
		arena = NULL;
		hose = NULL;
	}

	/* Third, iterate over the scatterlist leaders and allocate
	   dma space as needed.  */
	for (out = sg; sg < end; ++sg) {
		if ((int) sg->dma_address < 0)
			continue;
		if (sg_fill(dev, sg, end, out, arena, max_dma, dac_allowed) < 0)
			goto error;
		out++;
	}

	/* Mark the end of the list for pci_unmap_sg.  */
	if (out < end)
		out->dma_length = 0;

	if (out - start == 0) {
		printk(KERN_WARNING "pci_map_sg failed: no entries?\n");
		return -ENOMEM;
	}
	DBGA("pci_map_sg: %ld entries\n", out - start);

	return out - start;

 error:
	printk(KERN_WARNING "pci_map_sg failed: "
	       "could not allocate dma page tables\n");

	/* Some allocation failed while mapping the scatterlist
	   entries.  Unmap them now.  */
	if (out > start)
		dma_unmap_sg(&pdev->dev, start, out - start, dir);
	return -ENOMEM;
}

/* Unmap a set of streaming mode DMA translations.  Again, cpu read
   rules concerning calls here are the same as for pci_unmap_single()
   above.  */

static void alpha_pci_unmap_sg(struct device *dev, struct scatterlist *sg,
			       int nents, enum dma_data_direction dir,
			       unsigned long attrs)
{
	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
	unsigned long flags;
	struct pci_controller *hose;
	struct pci_iommu_arena *arena;
	struct scatterlist *end;
	dma_addr_t max_dma;
	dma_addr_t fbeg, fend;

	BUG_ON(dir == DMA_NONE);

	if (! alpha_mv.mv_pci_tbi)
		return;

	hose = pdev ? pdev->sysdata : pci_isa_hose;
	max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
	arena = hose->sg_pci;
	if (!arena || arena->dma_base + arena->size - 1 > max_dma)
		arena = hose->sg_isa;

	fbeg = -1, fend = 0;

	spin_lock_irqsave(&arena->lock, flags);

	for (end = sg + nents; sg < end; ++sg) {
		dma_addr_t addr;
		size_t size;
		long npages, ofs;
		dma_addr_t tend;

		addr = sg->dma_address;
		size = sg->dma_length;
		if (!size)
			break;

		if (addr > 0xffffffff) {
			/* It's a DAC address -- nothing to do.  */
			DBGA("    (%ld) DAC [%llx,%zx]\n",
			      sg - end + nents, addr, size);
			continue;
		}

		if (addr >= __direct_map_base
		    && addr < __direct_map_base + __direct_map_size) {
			/* Nothing to do.  */
			DBGA("    (%ld) direct [%llx,%zx]\n",
			      sg - end + nents, addr, size);
			continue;
		}

		DBGA("    (%ld) sg [%llx,%zx]\n",
		     sg - end + nents, addr, size);

		npages = iommu_num_pages(addr, size, PAGE_SIZE);
		ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
		iommu_arena_free(arena, ofs, npages);

		tend = addr + size - 1;
		if (fbeg > addr) fbeg = addr;
		if (fend < tend) fend = tend;
	}

        /* If we're freeing ptes above the `next_entry' pointer (they
           may have snuck back into the TLB since the last wrap flush),
           we need to flush the TLB before reallocating the latter.  */
	if ((fend - arena->dma_base) >> PAGE_SHIFT >= arena->next_entry)
		alpha_mv.mv_pci_tbi(hose, fbeg, fend);

	spin_unlock_irqrestore(&arena->lock, flags);

	DBGA("pci_unmap_sg: %ld entries\n", nents - (end - sg));
}

/* Return whether the given PCI device DMA address mask can be
   supported properly.  */

static int alpha_pci_supported(struct device *dev, u64 mask)
{
	struct pci_dev *pdev = alpha_gendev_to_pci(dev);
	struct pci_controller *hose;
	struct pci_iommu_arena *arena;

	/* If there exists a direct map, and the mask fits either
	   the entire direct mapped space or the total system memory as
	   shifted by the map base */
	if (__direct_map_size != 0
	    && (__direct_map_base + __direct_map_size - 1 <= mask ||
		__direct_map_base + (max_low_pfn << PAGE_SHIFT) - 1 <= mask))
		return 1;

	/* Check that we have a scatter-gather arena that fits.  */
	hose = pdev ? pdev->sysdata : pci_isa_hose;
	arena = hose->sg_isa;
	if (arena && arena->dma_base + arena->size - 1 <= mask)
		return 1;
	arena = hose->sg_pci;
	if (arena && arena->dma_base + arena->size - 1 <= mask)
		return 1;

	/* As last resort try ZONE_DMA.  */
	if (!__direct_map_base && MAX_DMA_ADDRESS - IDENT_ADDR - 1 <= mask)
		return 1;

	return 0;
}

/*
 * AGP GART extensions to the IOMMU
 */
int
iommu_reserve(struct pci_iommu_arena *arena, long pg_count, long align_mask)
{
	unsigned long flags;
	unsigned long *ptes;
	long i, p;

	if (!arena) return -EINVAL;

	spin_lock_irqsave(&arena->lock, flags);

	/* Search for N empty ptes.  */
	ptes = arena->ptes;
	p = iommu_arena_find_pages(NULL, arena, pg_count, align_mask);
	if (p < 0) {
		spin_unlock_irqrestore(&arena->lock, flags);
		return -1;
	}

	/* Success.  Mark them all reserved (ie not zero and invalid)
	   for the iommu tlb that could load them from under us.
	   They will be filled in with valid bits by _bind() */
	for (i = 0; i < pg_count; ++i)
		ptes[p+i] = IOMMU_RESERVED_PTE;

	arena->next_entry = p + pg_count;
	spin_unlock_irqrestore(&arena->lock, flags);

	return p;
}

int
iommu_release(struct pci_iommu_arena *arena, long pg_start, long pg_count)
{
	unsigned long *ptes;
	long i;

	if (!arena) return -EINVAL;

	ptes = arena->ptes;

	/* Make sure they're all reserved first... */
	for(i = pg_start; i < pg_start + pg_count; i++)
		if (ptes[i] != IOMMU_RESERVED_PTE)
			return -EBUSY;

	iommu_arena_free(arena, pg_start, pg_count);
	return 0;
}

int
iommu_bind(struct pci_iommu_arena *arena, long pg_start, long pg_count,
	   struct page **pages)
{
	unsigned long flags;
	unsigned long *ptes;
	long i, j;

	if (!arena) return -EINVAL;

	spin_lock_irqsave(&arena->lock, flags);

	ptes = arena->ptes;

	for(j = pg_start; j < pg_start + pg_count; j++) {
		if (ptes[j] != IOMMU_RESERVED_PTE) {
			spin_unlock_irqrestore(&arena->lock, flags);
			return -EBUSY;
		}
	}

	for(i = 0, j = pg_start; i < pg_count; i++, j++)
		ptes[j] = mk_iommu_pte(page_to_phys(pages[i]));

	spin_unlock_irqrestore(&arena->lock, flags);

	return 0;
}

int
iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
{
	unsigned long *p;
	long i;

	if (!arena) return -EINVAL;

	p = arena->ptes + pg_start;
	for(i = 0; i < pg_count; i++)
		p[i] = IOMMU_RESERVED_PTE;

	return 0;
}

const struct dma_map_ops alpha_pci_ops = {
	.alloc			= alpha_pci_alloc_coherent,
	.free			= alpha_pci_free_coherent,
	.map_page		= alpha_pci_map_page,
	.unmap_page		= alpha_pci_unmap_page,
	.map_sg			= alpha_pci_map_sg,
	.unmap_sg		= alpha_pci_unmap_sg,
	.dma_supported		= alpha_pci_supported,
	.mmap			= dma_common_mmap,
	.get_sgtable		= dma_common_get_sgtable,
	.alloc_pages		= dma_common_alloc_pages,
	.free_pages		= dma_common_free_pages,
};
EXPORT_SYMBOL(alpha_pci_ops);


code:
// SPDX-License-Identifier: GPL-2.0
/*
 * Hardware performance events for the Alpha.
 *
 * We implement HW counts on the EV67 and subsequent CPUs only.
 *
 * (C) 2010 Michael J. Cree
 *
 * Somewhat based on the Sparc code, and to a lesser extent the PowerPC and
 * ARM code, which are copyright by their respective authors.
 */

#include <linux/perf_event.h>
#include <linux/kprobes.h>
#include <linux/kernel.h>
#include <linux/kdebug.h>
#include <linux/mutex.h>
#include <linux/init.h>

#include <asm/hwrpb.h>
#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/irq_regs.h>
#include <asm/pal.h>
#include <asm/wrperfmon.h>
#include <asm/hw_irq.h>

/* The maximum number of PMCs on any Alpha CPU whatsoever. */
#define MAX_HWEVENTS 3
#define PMC_NO_INDEX -1

/* For tracking PMCs and the hw events they monitor on each CPU. */
struct cpu_hw_events {
	int			enabled;
	/* Number of events scheduled; also number entries valid in arrays below. */
	int			n_events;
	/* Number events added since last hw_perf_disable(). */
	int			n_added;
	/* Events currently scheduled. */
	struct perf_event	*event[MAX_HWEVENTS];
	/* Event type of each scheduled event. */
	unsigned long		evtype[MAX_HWEVENTS];
	/* Current index of each scheduled event; if not yet determined
	 * contains PMC_NO_INDEX.
	 */
	int			current_idx[MAX_HWEVENTS];
	/* The active PMCs' config for easy use with wrperfmon(). */
	unsigned long		config;
	/* The active counters' indices for easy use with wrperfmon(). */
	unsigned long		idx_mask;
};
DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);

/*
 * A structure to hold the description of the PMCs available on a particular
 * type of Alpha CPU.
 */
struct alpha_pmu_t {
	/* Mapping of the perf system hw event types to indigenous event types */
	const int *event_map;
	/* The number of entries in the event_map */
	int  max_events;
	/* The number of PMCs on this Alpha */
	int  num_pmcs;
	/*
	 * All PMC counters reside in the IBOX register PCTR.  This is the
	 * LSB of the counter.
	 */
	int  pmc_count_shift[MAX_HWEVENTS];
	/*
	 * The mask that isolates the PMC bits when the LSB of the counter
	 * is shifted to bit 0.
	 */
	unsigned long pmc_count_mask[MAX_HWEVENTS];
	/* The maximum period the PMC can count. */
	unsigned long pmc_max_period[MAX_HWEVENTS];
	/*
	 * The maximum value that may be written to the counter due to
	 * hardware restrictions is pmc_max_period - pmc_left.
	 */
	long pmc_left[3];
	 /* Subroutine for allocation of PMCs.  Enforces constraints. */
	int (*check_constraints)(struct perf_event **, unsigned long *, int);
	/* Subroutine for checking validity of a raw event for this PMU. */
	int (*raw_event_valid)(u64 config);
};

/*
 * The Alpha CPU PMU description currently in operation.  This is set during
 * the boot process to the specific CPU of the machine.
 */
static const struct alpha_pmu_t *alpha_pmu;

#define HW_OP_UNSUPPORTED -1

/*
 * The hardware description of the EV67, EV68, EV69, EV7 and EV79 PMUs
 * follow. Since they are identical we refer to them collectively as the
 * EV67 henceforth.
 */

/*
 * EV67 PMC event types
 *
 * There is no one-to-one mapping of the possible hw event types to the
 * actual codes that are used to program the PMCs hence we introduce our
 * own hw event type identifiers.
 */
enum ev67_pmc_event_type {
	EV67_CYCLES = 1,
	EV67_INSTRUCTIONS,
	EV67_BCACHEMISS,
	EV67_MBOXREPLAY,
	EV67_LAST_ET
};
#define EV67_NUM_EVENT_TYPES (EV67_LAST_ET-EV67_CYCLES)

/* Mapping of the hw event types to the perf tool interface */
static const int ev67_perfmon_event_map[] = {
	[PERF_COUNT_HW_CPU_CYCLES]	 = EV67_CYCLES,
	[PERF_COUNT_HW_INSTRUCTIONS]	 = EV67_INSTRUCTIONS,
	[PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
	[PERF_COUNT_HW_CACHE_MISSES]	 = EV67_BCACHEMISS,
};

struct ev67_mapping_t {
	int config;
	int idx;
};

/*
 * The mapping used for one event only - these must be in same order as enum
 * ev67_pmc_event_type definition.
 */
static const struct ev67_mapping_t ev67_mapping[] = {
	{EV67_PCTR_INSTR_CYCLES, 1},	 /* EV67_CYCLES, */
	{EV67_PCTR_INSTR_CYCLES, 0},	 /* EV67_INSTRUCTIONS */
	{EV67_PCTR_INSTR_BCACHEMISS, 1}, /* EV67_BCACHEMISS */
	{EV67_PCTR_CYCLES_MBOX, 1}	 /* EV67_MBOXREPLAY */
};

/*
 * Check that a group of events can be simultaneously scheduled on to the
 * EV67 PMU.  Also allocate counter indices and config.
 */
static int ev67_check_constraints(struct perf_event **event,
				unsigned long *evtype, int n_ev)
{
	int idx0;
	unsigned long config;

	idx0 = ev67_mapping[evtype[0]-1].idx;
	config = ev67_mapping[evtype[0]-1].config;
	if (n_ev == 1)
		goto success;

	BUG_ON(n_ev != 2);

	if (evtype[0] == EV67_MBOXREPLAY || evtype[1] == EV67_MBOXREPLAY) {
		/* MBOX replay traps must be on PMC 1 */
		idx0 = (evtype[0] == EV67_MBOXREPLAY) ? 1 : 0;
		/* Only cycles can accompany MBOX replay traps */
		if (evtype[idx0] == EV67_CYCLES) {
			config = EV67_PCTR_CYCLES_MBOX;
			goto success;
		}
	}

	if (evtype[0] == EV67_BCACHEMISS || evtype[1] == EV67_BCACHEMISS) {
		/* Bcache misses must be on PMC 1 */
		idx0 = (evtype[0] == EV67_BCACHEMISS) ? 1 : 0;
		/* Only instructions can accompany Bcache misses */
		if (evtype[idx0] == EV67_INSTRUCTIONS) {
			config = EV67_PCTR_INSTR_BCACHEMISS;
			goto success;
		}
	}

	if (evtype[0] == EV67_INSTRUCTIONS || evtype[1] == EV67_INSTRUCTIONS) {
		/* Instructions must be on PMC 0 */
		idx0 = (evtype[0] == EV67_INSTRUCTIONS) ? 0 : 1;
		/* By this point only cycles can accompany instructions */
		if (evtype[idx0^1] == EV67_CYCLES) {
			config = EV67_PCTR_INSTR_CYCLES;
			goto success;
		}
	}

	/* Otherwise, darn it, there is a conflict.  */
	return -1;

success:
	event[0]->hw.idx = idx0;
	event[0]->hw.config_base = config;
	if (n_ev == 2) {
		event[1]->hw.idx = idx0 ^ 1;
		event[1]->hw.config_base = config;
	}
	return 0;
}

static int ev67_raw_event_valid(u64 config)
{
	return config >= EV67_CYCLES && config < EV67_LAST_ET;
};

static const struct alpha_pmu_t ev67_pmu = {
	.event_map = ev67_perfmon_event_map,
	.max_events = ARRAY_SIZE(ev67_perfmon_event_map),
	.num_pmcs = 2,
	.pmc_count_shift = {EV67_PCTR_0_COUNT_SHIFT, EV67_PCTR_1_COUNT_SHIFT, 0},
	.pmc_count_mask = {EV67_PCTR_0_COUNT_MASK,  EV67_PCTR_1_COUNT_MASK,  0},
	.pmc_max_period = {(1UL<<20) - 1, (1UL<<20) - 1, 0},
	.pmc_left = {16, 4, 0},
	.check_constraints = ev67_check_constraints,
	.raw_event_valid = ev67_raw_event_valid,
};

/*
 * Helper routines to ensure that we read/write only the correct PMC bits
 * when calling the wrperfmon PALcall.
 */
static inline void alpha_write_pmc(int idx, unsigned long val)
{
	val &= alpha_pmu->pmc_count_mask[idx];
	val <<= alpha_pmu->pmc_count_shift[idx];
	val |= (1<<idx);
	wrperfmon(PERFMON_CMD_WRITE, val);
}

static inline unsigned long alpha_read_pmc(int idx)
{
	unsigned long val;

	val = wrperfmon(PERFMON_CMD_READ, 0);
	val >>= alpha_pmu->pmc_count_shift[idx];
	val &= alpha_pmu->pmc_count_mask[idx];
	return val;
}

/* Set a new period to sample over */
static int alpha_perf_event_set_period(struct perf_event *event,
				struct hw_perf_event *hwc, int idx)
{
	long left = local64_read(&hwc->period_left);
	long period = hwc->sample_period;
	int ret = 0;

	if (unlikely(left <= -period)) {
		left = period;
		local64_set(&hwc->period_left, left);
		hwc->last_period = period;
		ret = 1;
	}

	if (unlikely(left <= 0)) {
		left += period;
		local64_set(&hwc->period_left, left);
		hwc->last_period = period;
		ret = 1;
	}

	/*
	 * Hardware restrictions require that the counters must not be
	 * written with values that are too close to the maximum period.
	 */
	if (unlikely(left < alpha_pmu->pmc_left[idx]))
		left = alpha_pmu->pmc_left[idx];

	if (left > (long)alpha_pmu->pmc_max_period[idx])
		left = alpha_pmu->pmc_max_period[idx];

	local64_set(&hwc->prev_count, (unsigned long)(-left));

	alpha_write_pmc(idx, (unsigned long)(-left));

	perf_event_update_userpage(event);

	return ret;
}

/*
 * Calculates the count (the 'delta') since the last time the PMC was read.
 *
 * As the PMCs' full period can easily be exceeded within the perf system
 * sampling period we cannot use any high order bits as a guard bit in the
 * PMCs to detect overflow as is done by other architectures.  The code here
 * calculates the delta on the basis that there is no overflow when ovf is
 * zero.  The value passed via ovf by the interrupt handler corrects for
 * overflow.
 *
 * This can be racey on rare occasions -- a call to this routine can occur
 * with an overflowed counter just before the PMI service routine is called.
 * The check for delta negative hopefully always rectifies this situation.
 */
static unsigned long alpha_perf_event_update(struct perf_event *event,
					struct hw_perf_event *hwc, int idx, long ovf)
{
	long prev_raw_count, new_raw_count;
	long delta;

again:
	prev_raw_count = local64_read(&hwc->prev_count);
	new_raw_count = alpha_read_pmc(idx);

	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
			     new_raw_count) != prev_raw_count)
		goto again;

	delta = (new_raw_count - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;

	/* It is possible on very rare occasions that the PMC has overflowed
	 * but the interrupt is yet to come.  Detect and fix this situation.
	 */
	if (unlikely(delta < 0)) {
		delta += alpha_pmu->pmc_max_period[idx] + 1;
	}

	local64_add(delta, &event->count);
	local64_sub(delta, &hwc->period_left);

	return new_raw_count;
}

/*
 * Collect all HW events into the array event[].
 */
static int collect_events(struct perf_event *group, int max_count,
			  struct perf_event *event[], unsigned long *evtype,
			  int *current_idx)
{
	struct perf_event *pe;
	int n = 0;

	if (!is_software_event(group)) {
		if (n >= max_count)
			return -1;
		event[n] = group;
		evtype[n] = group->hw.event_base;
		current_idx[n++] = PMC_NO_INDEX;
	}
	for_each_sibling_event(pe, group) {
		if (!is_software_event(pe) && pe->state != PERF_EVENT_STATE_OFF) {
			if (n >= max_count)
				return -1;
			event[n] = pe;
			evtype[n] = pe->hw.event_base;
			current_idx[n++] = PMC_NO_INDEX;
		}
	}
	return n;
}

/*
 * Check that a group of events can be simultaneously scheduled on to the PMU.
 */
static int alpha_check_constraints(struct perf_event **events,
				   unsigned long *evtypes, int n_ev)
{

	/* No HW events is possible from hw_perf_group_sched_in(). */
	if (n_ev == 0)
		return 0;

	if (n_ev > alpha_pmu->num_pmcs)
		return -1;

	return alpha_pmu->check_constraints(events, evtypes, n_ev);
}

/*
 * If new events have been scheduled then update cpuc with the new
 * configuration.  This may involve shifting cycle counts from one PMC to
 * another.
 */
static void maybe_change_configuration(struct cpu_hw_events *cpuc)
{
	int j;

	if (cpuc->n_added == 0)
		return;

	/* Find counters that are moving to another PMC and update */
	for (j = 0; j < cpuc->n_events; j++) {
		struct perf_event *pe = cpuc->event[j];

		if (cpuc->current_idx[j] != PMC_NO_INDEX &&
			cpuc->current_idx[j] != pe->hw.idx) {
			alpha_perf_event_update(pe, &pe->hw, cpuc->current_idx[j], 0);
			cpuc->current_idx[j] = PMC_NO_INDEX;
		}
	}

	/* Assign to counters all unassigned events. */
	cpuc->idx_mask = 0;
	for (j = 0; j < cpuc->n_events; j++) {
		struct perf_event *pe = cpuc->event[j];
		struct hw_perf_event *hwc = &pe->hw;
		int idx = hwc->idx;

		if (cpuc->current_idx[j] == PMC_NO_INDEX) {
			alpha_perf_event_set_period(pe, hwc, idx);
			cpuc->current_idx[j] = idx;
		}

		if (!(hwc->state & PERF_HES_STOPPED))
			cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
	}
	cpuc->config = cpuc->event[0]->hw.config_base;
}

/* Schedule perf HW event on to PMU.
 *  - this function is called from outside this module via the pmu struct
 *    returned from perf event initialisation.
 */
static int alpha_pmu_add(struct perf_event *event, int flags)
{
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
	struct hw_perf_event *hwc = &event->hw;
	int n0;
	int ret;
	unsigned long irq_flags;

	/*
	 * The Sparc code has the IRQ disable first followed by the perf
	 * disable, however this can lead to an overflowed counter with the
	 * PMI disabled on rare occasions.  The alpha_perf_event_update()
	 * routine should detect this situation by noting a negative delta,
	 * nevertheless we disable the PMCs first to enable a potential
	 * final PMI to occur before we disable interrupts.
	 */
	perf_pmu_disable(event->pmu);
	local_irq_save(irq_flags);

	/* Default to error to be returned */
	ret = -EAGAIN;

	/* Insert event on to PMU and if successful modify ret to valid return */
	n0 = cpuc->n_events;
	if (n0 < alpha_pmu->num_pmcs) {
		cpuc->event[n0] = event;
		cpuc->evtype[n0] = event->hw.event_base;
		cpuc->current_idx[n0] = PMC_NO_INDEX;

		if (!alpha_check_constraints(cpuc->event, cpuc->evtype, n0+1)) {
			cpuc->n_events++;
			cpuc->n_added++;
			ret = 0;
		}
	}

	hwc->state = PERF_HES_UPTODATE;
	if (!(flags & PERF_EF_START))
		hwc->state |= PERF_HES_STOPPED;

	local_irq_restore(irq_flags);
	perf_pmu_enable(event->pmu);

	return ret;
}

/* Disable performance monitoring unit
 *  - this function is called from outside this module via the pmu struct
 *    returned from perf event initialisation.
 */
static void alpha_pmu_del(struct perf_event *event, int flags)
{
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
	struct hw_perf_event *hwc = &event->hw;
	unsigned long irq_flags;
	int j;

	perf_pmu_disable(event->pmu);
	local_irq_save(irq_flags);

	for (j = 0; j < cpuc->n_events; j++) {
		if (event == cpuc->event[j]) {
			int idx = cpuc->current_idx[j];

			/* Shift remaining entries down into the existing
			 * slot.
			 */
			while (++j < cpuc->n_events) {
				cpuc->event[j - 1] = cpuc->event[j];
				cpuc->evtype[j - 1] = cpuc->evtype[j];
				cpuc->current_idx[j - 1] =
					cpuc->current_idx[j];
			}

			/* Absorb the final count and turn off the event. */
			alpha_perf_event_update(event, hwc, idx, 0);
			perf_event_update_userpage(event);

			cpuc->idx_mask &= ~(1UL<<idx);
			cpuc->n_events--;
			break;
		}
	}

	local_irq_restore(irq_flags);
	perf_pmu_enable(event->pmu);
}

static void alpha_pmu_read(struct perf_event *event)
{
	struct hw_perf_event *hwc = &event->hw;

	alpha_perf_event_update(event, hwc, hwc->idx, 0);
}

static void alpha_pmu_stop(struct perf_event *event, int flags)
{
	struct hw_perf_event *hwc = &event->hw;
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);

	if (!(hwc->state & PERF_HES_STOPPED)) {
		cpuc->idx_mask &= ~(1UL<<hwc->idx);
		hwc->state |= PERF_HES_STOPPED;
	}

	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
		alpha_perf_event_update(event, hwc, hwc->idx, 0);
		hwc->state |= PERF_HES_UPTODATE;
	}

	if (cpuc->enabled)
		wrperfmon(PERFMON_CMD_DISABLE, (1UL<<hwc->idx));
}

static void alpha_pmu_start(struct perf_event *event, int flags)
{
	struct hw_perf_event *hwc = &event->hw;
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);

	if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
		return;

	if (flags & PERF_EF_RELOAD) {
		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
		alpha_perf_event_set_period(event, hwc, hwc->idx);
	}

	hwc->state = 0;

	cpuc->idx_mask |= 1UL<<hwc->idx;
	if (cpuc->enabled)
		wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
}

/*
 * Check that CPU performance counters are supported.
 * - currently support EV67 and later CPUs.
 * - actually some later revisions of the EV6 have the same PMC model as the
 *     EV67 but we don't do sufficiently deep CPU detection to detect them.
 *     Bad luck to the very few people who might have one, I guess.
 */
static int supported_cpu(void)
{
	struct percpu_struct *cpu;
	unsigned long cputype;

	/* Get cpu type from HW */
	cpu = (struct percpu_struct *)((char *)hwrpb + hwrpb->processor_offset);
	cputype = cpu->type & 0xffffffff;
	/* Include all of EV67, EV68, EV7, EV79 and EV69 as supported. */
	return (cputype >= EV67_CPU) && (cputype <= EV69_CPU);
}

static void hw_perf_event_destroy(struct perf_event *event)
{
	/* Nothing to be done! */
	return;
}

static int __hw_perf_event_init(struct perf_event *event)
{
	struct perf_event_attr *attr = &event->attr;
	struct hw_perf_event *hwc = &event->hw;
	struct perf_event *evts[MAX_HWEVENTS];
	unsigned long evtypes[MAX_HWEVENTS];
	int idx_rubbish_bin[MAX_HWEVENTS];
	int ev;
	int n;

	/* We only support a limited range of HARDWARE event types with one
	 * only programmable via a RAW event type.
	 */
	if (attr->type == PERF_TYPE_HARDWARE) {
		if (attr->config >= alpha_pmu->max_events)
			return -EINVAL;
		ev = alpha_pmu->event_map[attr->config];
	} else if (attr->type == PERF_TYPE_HW_CACHE) {
		return -EOPNOTSUPP;
	} else if (attr->type == PERF_TYPE_RAW) {
		if (!alpha_pmu->raw_event_valid(attr->config))
			return -EINVAL;
		ev = attr->config;
	} else {
		return -EOPNOTSUPP;
	}

	if (ev < 0) {
		return ev;
	}

	/*
	 * We place the event type in event_base here and leave calculation
	 * of the codes to programme the PMU for alpha_pmu_enable() because
	 * it is only then we will know what HW events are actually
	 * scheduled on to the PMU.  At that point the code to programme the
	 * PMU is put into config_base and the PMC to use is placed into
	 * idx.  We initialise idx (below) to PMC_NO_INDEX to indicate that
	 * it is yet to be determined.
	 */
	hwc->event_base = ev;

	/* Collect events in a group together suitable for calling
	 * alpha_check_constraints() to verify that the group as a whole can
	 * be scheduled on to the PMU.
	 */
	n = 0;
	if (event->group_leader != event) {
		n = collect_events(event->group_leader,
				alpha_pmu->num_pmcs - 1,
				evts, evtypes, idx_rubbish_bin);
		if (n < 0)
			return -EINVAL;
	}
	evtypes[n] = hwc->event_base;
	evts[n] = event;

	if (alpha_check_constraints(evts, evtypes, n + 1))
		return -EINVAL;

	/* Indicate that PMU config and idx are yet to be determined. */
	hwc->config_base = 0;
	hwc->idx = PMC_NO_INDEX;

	event->destroy = hw_perf_event_destroy;

	/*
	 * Most architectures reserve the PMU for their use at this point.
	 * As there is no existing mechanism to arbitrate usage and there
	 * appears to be no other user of the Alpha PMU we just assume
	 * that we can just use it, hence a NO-OP here.
	 *
	 * Maybe an alpha_reserve_pmu() routine should be implemented but is
	 * anything else ever going to use it?
	 */

	if (!hwc->sample_period) {
		hwc->sample_period = alpha_pmu->pmc_max_period[0];
		hwc->last_period = hwc->sample_period;
		local64_set(&hwc->period_left, hwc->sample_period);
	}

	return 0;
}

/*
 * Main entry point to initialise a HW performance event.
 */
static int alpha_pmu_event_init(struct perf_event *event)
{
	int err;

	/* does not support taken branch sampling */
	if (has_branch_stack(event))
		return -EOPNOTSUPP;

	switch (event->attr.type) {
	case PERF_TYPE_RAW:
	case PERF_TYPE_HARDWARE:
	case PERF_TYPE_HW_CACHE:
		break;

	default:
		return -ENOENT;
	}

	if (!alpha_pmu)
		return -ENODEV;

	/* Do the real initialisation work. */
	err = __hw_perf_event_init(event);

	return err;
}

/*
 * Main entry point - enable HW performance counters.
 */
static void alpha_pmu_enable(struct pmu *pmu)
{
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);

	if (cpuc->enabled)
		return;

	cpuc->enabled = 1;
	barrier();

	if (cpuc->n_events > 0) {
		/* Update cpuc with information from any new scheduled events. */
		maybe_change_configuration(cpuc);

		/* Start counting the desired events. */
		wrperfmon(PERFMON_CMD_LOGGING_OPTIONS, EV67_PCTR_MODE_AGGREGATE);
		wrperfmon(PERFMON_CMD_DESIRED_EVENTS, cpuc->config);
		wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
	}
}

/*
 * Main entry point - disable HW performance counters.
 */

static void alpha_pmu_disable(struct pmu *pmu)
{
	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);

	if (!cpuc->enabled)
		return;

	cpuc->enabled = 0;
	cpuc->n_added = 0;

	wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
}

static struct pmu pmu = {
	.pmu_enable	= alpha_pmu_enable,
	.pmu_disable	= alpha_pmu_disable,
	.event_init	= alpha_pmu_event_init,
	.add		= alpha_pmu_add,
	.del		= alpha_pmu_del,
	.start		= alpha_pmu_start,
	.stop		= alpha_pmu_stop,
	.read		= alpha_pmu_read,
	.capabilities	= PERF_PMU_CAP_NO_EXCLUDE,
};

/*
 * Main entry point - don't know when this is called but it
 * obviously dumps debug info.
 */
void perf_event_print_debug(void)
{
	unsigned long flags;
	unsigned long pcr;
	int pcr0, pcr1;
	int cpu;

	if (!supported_cpu())
		return;

	local_irq_save(flags);

	cpu = smp_processor_id();

	pcr = wrperfmon(PERFMON_CMD_READ, 0);
	pcr0 = (pcr >> alpha_pmu->pmc_count_shift[0]) & alpha_pmu->pmc_count_mask[0];
	pcr1 = (pcr >> alpha_pmu->pmc_count_shift[1]) & alpha_pmu->pmc_count_mask[1];

	pr_info("CPU#%d: PCTR0[%06x] PCTR1[%06x]\n", cpu, pcr0, pcr1);

	local_irq_restore(flags);
}

/*
 * Performance Monitoring Interrupt Service Routine called when a PMC
 * overflows.  The PMC that overflowed is passed in la_ptr.
 */
static void alpha_perf_event_irq_handler(unsigned long la_ptr,
					struct pt_regs *regs)
{
	struct cpu_hw_events *cpuc;
	struct perf_sample_data data;
	struct perf_event *event;
	struct hw_perf_event *hwc;
	int idx, j;

	__this_cpu_inc(irq_pmi_count);
	cpuc = this_cpu_ptr(&cpu_hw_events);

	/* Completely counting through the PMC's period to trigger a new PMC
	 * overflow interrupt while in this interrupt routine is utterly
	 * disastrous!  The EV6 and EV67 counters are sufficiently large to
	 * prevent this but to be really sure disable the PMCs.
	 */
	wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);

	/* la_ptr is the counter that overflowed. */
	if (unlikely(la_ptr >= alpha_pmu->num_pmcs)) {
		/* This should never occur! */
		irq_err_count++;
		pr_warn("PMI: silly index %ld\n", la_ptr);
		wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
		return;
	}

	idx = la_ptr;

	for (j = 0; j < cpuc->n_events; j++) {
		if (cpuc->current_idx[j] == idx)
			break;
	}

	if (unlikely(j == cpuc->n_events)) {
		/* This can occur if the event is disabled right on a PMC overflow. */
		wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
		return;
	}

	event = cpuc->event[j];

	if (unlikely(!event)) {
		/* This should never occur! */
		irq_err_count++;
		pr_warn("PMI: No event at index %d!\n", idx);
		wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
		return;
	}

	hwc = &event->hw;
	alpha_perf_event_update(event, hwc, idx, alpha_pmu->pmc_max_period[idx]+1);
	perf_sample_data_init(&data, 0, hwc->last_period);

	if (alpha_perf_event_set_period(event, hwc, idx)) {
		if (perf_event_overflow(event, &data, regs)) {
			/* Interrupts coming too quickly; "throttle" the
			 * counter, i.e., disable it for a little while.
			 */
			alpha_pmu_stop(event, 0);
		}
	}
	wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);

	return;
}

/*
 * Init call to initialise performance events at kernel startup.
 */
int __init init_hw_perf_events(void)
{
	pr_info("Performance events: ");

	if (!supported_cpu()) {
		pr_cont("No support for your CPU.\n");
		return 0;
	}

	pr_cont("Supported CPU type!\n");

	/* Override performance counter IRQ vector */

	perf_irq = alpha_perf_event_irq_handler;

	/* And set up PMU specification */
	alpha_pmu = &ev67_pmu;

	perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);

	return 0;
}
early_initcall(init_hw_perf_events);

repo_name: angery/linux


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *  linux/arch/alpha/kernel/process.c
 *
 *  Copyright (C) 1995  Linus Torvalds
 */

/*
 * This file handles the architecture-dependent parts of process handling.
 */

#include <linux/errno.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
#include <linux/sched/task.h>
#include <linux/sched/task_stack.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/time.h>
#include <linux/major.h>
#include <linux/stat.h>
#include <linux/vt.h>
#include <linux/mman.h>
#include <linux/elfcore.h>
#include <linux/reboot.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/slab.h>
#include <linux/rcupdate.h>

#include <asm/reg.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
#include <asm/fpu.h>

#include "proto.h"
#include "pci_impl.h"

/*
 * Power off function, if any
 */
void (*pm_power_off)(void) = machine_power_off;
EXPORT_SYMBOL(pm_power_off);

#ifdef CONFIG_ALPHA_WTINT
/*
 * Sleep the CPU.
 * EV6, LCA45 and QEMU know how to power down, skipping N timer interrupts.
 */
void arch_cpu_idle(void)
{
	wtint(0);
	raw_local_irq_enable();
}

void arch_cpu_idle_dead(void)
{
	wtint(INT_MAX);
}
#endif /* ALPHA_WTINT */

struct halt_info {
	int mode;
	char *restart_cmd;
};

static void
common_shutdown_1(void *generic_ptr)
{
	struct halt_info *how = (struct halt_info *)generic_ptr;
	struct percpu_struct *cpup;
	unsigned long *pflags, flags;
	int cpuid = smp_processor_id();

	/* No point in taking interrupts anymore. */
	local_irq_disable();

	cpup = (struct percpu_struct *)
			((unsigned long)hwrpb + hwrpb->processor_offset
			 + hwrpb->processor_size * cpuid);
	pflags = &cpup->flags;
	flags = *pflags;

	/* Clear reason to "default"; clear "bootstrap in progress". */
	flags &= ~0x00ff0001UL;

#ifdef CONFIG_SMP
	/* Secondaries halt here. */
	if (cpuid != boot_cpuid) {
		flags |= 0x00040000UL; /* "remain halted" */
		*pflags = flags;
		set_cpu_present(cpuid, false);
		set_cpu_possible(cpuid, false);
		halt();
	}
#endif

	if (how->mode == LINUX_REBOOT_CMD_RESTART) {
		if (!how->restart_cmd) {
			flags |= 0x00020000UL; /* "cold bootstrap" */
		} else {
			/* For SRM, we could probably set environment
			   variables to get this to work.  We'd have to
			   delay this until after srm_paging_stop unless
			   we ever got srm_fixup working.

			   At the moment, SRM will use the last boot device,
			   but the file and flags will be the defaults, when
			   doing a "warm" bootstrap.  */
			flags |= 0x00030000UL; /* "warm bootstrap" */
		}
	} else {
		flags |= 0x00040000UL; /* "remain halted" */
	}
	*pflags = flags;

#ifdef CONFIG_SMP
	/* Wait for the secondaries to halt. */
	set_cpu_present(boot_cpuid, false);
	set_cpu_possible(boot_cpuid, false);
	while (!cpumask_empty(cpu_present_mask))
		barrier();
#endif

	/* If booted from SRM, reset some of the original environment. */
	if (alpha_using_srm) {
#ifdef CONFIG_DUMMY_CONSOLE
		/* If we've gotten here after SysRq-b, leave interrupt
		   context before taking over the console. */
		if (in_irq())
			irq_exit();
		/* This has the effect of resetting the VGA video origin.  */
		console_lock();
		do_take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1);
		console_unlock();
#endif
		pci_restore_srm_config();
		set_hae(srm_hae);
	}

	if (alpha_mv.kill_arch)
		alpha_mv.kill_arch(how->mode);

	if (! alpha_using_srm && how->mode != LINUX_REBOOT_CMD_RESTART) {
		/* Unfortunately, since MILO doesn't currently understand
		   the hwrpb bits above, we can't reliably halt the
		   processor and keep it halted.  So just loop.  */
		return;
	}

	if (alpha_using_srm)
		srm_paging_stop();

	halt();
}

static void
common_shutdown(int mode, char *restart_cmd)
{
	struct halt_info args;
	args.mode = mode;
	args.restart_cmd = restart_cmd;
	on_each_cpu(common_shutdown_1, &args, 0);
}

void
machine_restart(char *restart_cmd)
{
	common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd);
}

void
machine_halt(void)
{
	common_shutdown(LINUX_REBOOT_CMD_HALT, NULL);
}

void
machine_power_off(void)
{
	common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
}

/* Used by sysrq-p, among others.  I don't believe r9-r15 are ever
   saved in the context it's used.  */

void
show_regs(struct pt_regs *regs)
{
	show_regs_print_info(KERN_DEFAULT);
	dik_show_regs(regs, NULL);
}

/*
 * Re-start a thread when doing execve()
 */
void
start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
{
	regs->pc = pc;
	regs->ps = 8;
	wrusp(sp);
}
EXPORT_SYMBOL(start_thread);

void
flush_thread(void)
{
	/* Arrange for each exec'ed process to start off with a clean slate
	   with respect to the FPU.  This is all exceptions disabled.  */
	current_thread_info()->ieee_state = 0;
	wrfpcr(FPCR_DYN_NORMAL | ieee_swcr_to_fpcr(0));

	/* Clean slate for TLS.  */
	current_thread_info()->pcb.unique = 0;
}

/*
 * Copy architecture-specific thread state
 */
int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
{
	unsigned long clone_flags = args->flags;
	unsigned long usp = args->stack;
	unsigned long tls = args->tls;
	extern void ret_from_fork(void);
	extern void ret_from_kernel_thread(void);

	struct thread_info *childti = task_thread_info(p);
	struct pt_regs *childregs = task_pt_regs(p);
	struct pt_regs *regs = current_pt_regs();
	struct switch_stack *childstack, *stack;

	childstack = ((struct switch_stack *) childregs) - 1;
	childti->pcb.ksp = (unsigned long) childstack;
	childti->pcb.flags = 1;	/* set FEN, clear everything else */

	if (unlikely(args->fn)) {
		/* kernel thread */
		memset(childstack, 0,
			sizeof(struct switch_stack) + sizeof(struct pt_regs));
		childstack->r26 = (unsigned long) ret_from_kernel_thread;
		childstack->r9 = (unsigned long) args->fn;
		childstack->r10 = (unsigned long) args->fn_arg;
		childregs->hae = alpha_mv.hae_cache;
		childti->pcb.usp = 0;
		return 0;
	}
	/* Note: if CLONE_SETTLS is not set, then we must inherit the
	   value from the parent, which will have been set by the block
	   copy in dup_task_struct.  This is non-intuitive, but is
	   required for proper operation in the case of a threaded
	   application calling fork.  */
	if (clone_flags & CLONE_SETTLS)
		childti->pcb.unique = tls;
	else
		regs->r20 = 0;	/* OSF/1 has some strange fork() semantics.  */
	childti->pcb.usp = usp ?: rdusp();
	*childregs = *regs;
	childregs->r0 = 0;
	childregs->r19 = 0;
	childregs->r20 = 1;	/* OSF/1 has some strange fork() semantics.  */
	stack = ((struct switch_stack *) regs) - 1;
	*childstack = *stack;
	childstack->r26 = (unsigned long) ret_from_fork;
	return 0;
}

/*
 * Fill in the user structure for a ELF core dump.
 */
void
dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
{
	/* switch stack follows right below pt_regs: */
	struct switch_stack * sw = ((struct switch_stack *) pt) - 1;

	dest[ 0] = pt->r0;
	dest[ 1] = pt->r1;
	dest[ 2] = pt->r2;
	dest[ 3] = pt->r3;
	dest[ 4] = pt->r4;
	dest[ 5] = pt->r5;
	dest[ 6] = pt->r6;
	dest[ 7] = pt->r7;
	dest[ 8] = pt->r8;
	dest[ 9] = sw->r9;
	dest[10] = sw->r10;
	dest[11] = sw->r11;
	dest[12] = sw->r12;
	dest[13] = sw->r13;
	dest[14] = sw->r14;
	dest[15] = sw->r15;
	dest[16] = pt->r16;
	dest[17] = pt->r17;
	dest[18] = pt->r18;
	dest[19] = pt->r19;
	dest[20] = pt->r20;
	dest[21] = pt->r21;
	dest[22] = pt->r22;
	dest[23] = pt->r23;
	dest[24] = pt->r24;
	dest[25] = pt->r25;
	dest[26] = pt->r26;
	dest[27] = pt->r27;
	dest[28] = pt->r28;
	dest[29] = pt->gp;
	dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp;
	dest[31] = pt->pc;

	/* Once upon a time this was the PS value.  Which is stupid
	   since that is always 8 for usermode.  Usurped for the more
	   useful value of the thread's UNIQUE field.  */
	dest[32] = ti->pcb.unique;
}
EXPORT_SYMBOL(dump_elf_thread);

int
dump_elf_task(elf_greg_t *dest, struct task_struct *task)
{
	dump_elf_thread(dest, task_pt_regs(task), task_thread_info(task));
	return 1;
}
EXPORT_SYMBOL(dump_elf_task);

int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{
	struct switch_stack *sw = (struct switch_stack *)task_pt_regs(t) - 1;
	memcpy(fpu, sw->fp, 32 * 8);
	return 1;
}

/*
 * Return saved PC of a blocked thread.  This assumes the frame
 * pointer is the 6th saved long on the kernel stack and that the
 * saved return address is the first long in the frame.  This all
 * holds provided the thread blocked through a call to schedule() ($15
 * is the frame pointer in schedule() and $15 is saved at offset 48 by
 * entry.S:do_switch_stack).
 *
 * Under heavy swap load I've seen this lose in an ugly way.  So do
 * some extra sanity checking on the ranges we expect these pointers
 * to be in so that we can fail gracefully.  This is just for ps after
 * all.  -- r~
 */

static unsigned long
thread_saved_pc(struct task_struct *t)
{
	unsigned long base = (unsigned long)task_stack_page(t);
	unsigned long fp, sp = task_thread_info(t)->pcb.ksp;

	if (sp > base && sp+6*8 < base + 16*1024) {
		fp = ((unsigned long*)sp)[6];
		if (fp > sp && fp < base + 16*1024)
			return *(unsigned long *)fp;
	}

	return 0;
}

unsigned long
__get_wchan(struct task_struct *p)
{
	unsigned long schedule_frame;
	unsigned long pc;

	/*
	 * This one depends on the frame size of schedule().  Do a
	 * "disass schedule" in gdb to find the frame size.  Also, the
	 * code assumes that sleep_on() follows immediately after
	 * interruptible_sleep_on() and that add_timer() follows
	 * immediately after interruptible_sleep().  Ugly, isn't it?
	 * Maybe adding a wchan field to task_struct would be better,
	 * after all...
	 */

	pc = thread_saved_pc(p);
	if (in_sched_functions(pc)) {
		schedule_frame = ((unsigned long *)task_thread_info(p)->pcb.ksp)[6];
		return ((unsigned long *)schedule_frame)[12];
	}
	return pc;
}


code:
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/interrupt.h>
#include <linux/io.h>

/* Prototypes of functions used across modules here in this directory.  */

#define vucp	volatile unsigned char  *
#define vusp	volatile unsigned short *
#define vip	volatile int *
#define vuip	volatile unsigned int   *
#define vulp	volatile unsigned long  *

struct pt_regs;
struct task_struct;
struct pci_dev;
struct pci_controller;

/* core_apecs.c */
extern struct pci_ops apecs_pci_ops;
extern void apecs_init_arch(void);
extern void apecs_pci_clr_err(void);
extern void apecs_machine_check(unsigned long vector, unsigned long la_ptr);
extern void apecs_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);

/* core_cia.c */
extern struct pci_ops cia_pci_ops;
extern void cia_init_pci(void);
extern void cia_init_arch(void);
extern void pyxis_init_arch(void);
extern void cia_kill_arch(int);
extern void cia_machine_check(unsigned long vector, unsigned long la_ptr);
extern void cia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);

/* core_irongate.c */
extern struct pci_ops irongate_pci_ops;
extern int irongate_pci_clr_err(void);
extern void irongate_init_arch(void);
#define irongate_pci_tbi ((void *)0)

/* core_lca.c */
extern struct pci_ops lca_pci_ops;
extern void lca_init_arch(void);
extern void lca_machine_check(unsigned long vector, unsigned long la_ptr);
extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);

/* core_marvel.c */
extern struct pci_ops marvel_pci_ops;
extern void marvel_init_arch(void);
extern void marvel_kill_arch(int);
extern void marvel_machine_check(unsigned long, unsigned long);
extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct _alpha_agp_info *marvel_agp_info(void);
struct io7 *marvel_find_io7(int pe);
struct io7 *marvel_next_io7(struct io7 *prev);
void io7_clear_errors(struct io7 *io7);

/* core_mcpcia.c */
extern struct pci_ops mcpcia_pci_ops;
extern void mcpcia_init_arch(void);
extern void mcpcia_init_hoses(void);
extern void mcpcia_machine_check(unsigned long vector, unsigned long la_ptr);
extern void mcpcia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);

/* core_polaris.c */
extern struct pci_ops polaris_pci_ops;
extern int polaris_read_config_dword(struct pci_dev *, int, u32 *);
extern int polaris_write_config_dword(struct pci_dev *, int, u32);
extern void polaris_init_arch(void);
extern void polaris_machine_check(unsigned long vector, unsigned long la_ptr);
#define polaris_pci_tbi ((void *)0)

/* core_t2.c */
extern struct pci_ops t2_pci_ops;
extern void t2_init_arch(void);
extern void t2_kill_arch(int);
extern void t2_machine_check(unsigned long vector, unsigned long la_ptr);
extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);

/* core_titan.c */
extern struct pci_ops titan_pci_ops;
extern void titan_init_arch(void);
extern void titan_kill_arch(int);
extern void titan_machine_check(unsigned long, unsigned long);
extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct _alpha_agp_info *titan_agp_info(void);

/* core_tsunami.c */
extern struct pci_ops tsunami_pci_ops;
extern void tsunami_init_arch(void);
extern void tsunami_kill_arch(int);
extern void tsunami_machine_check(unsigned long vector, unsigned long la_ptr);
extern void tsunami_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);

/* core_wildfire.c */
extern struct pci_ops wildfire_pci_ops;
extern void wildfire_init_arch(void);
extern void wildfire_kill_arch(int);
extern void wildfire_machine_check(unsigned long vector, unsigned long la_ptr);
extern void wildfire_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);

/* console.c */
#ifdef CONFIG_VGA_HOSE
extern void find_console_vga_hose(void);
extern void locate_and_init_vga(void *(*)(void *, void *));
#else
static inline void find_console_vga_hose(void) { }
static inline void locate_and_init_vga(void *(*sel_func)(void *, void *)) { }
#endif

/* setup.c */
extern unsigned long srm_hae;
extern int boot_cpuid;
#ifdef CONFIG_VERBOSE_MCHECK
extern unsigned long alpha_verbose_mcheck;
#endif

/* srmcons.c */
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
extern void register_srm_console(void);
extern void unregister_srm_console(void);
#else
#define register_srm_console()
#define unregister_srm_console()
#endif

/* smp.c */
extern void setup_smp(void);
extern void handle_ipi(struct pt_regs *);

/* bios32.c */
/* extern void reset_for_srm(void); */

/* time.c */
extern irqreturn_t rtc_timer_interrupt(int irq, void *dev);
extern void init_clockevent(void);
extern void common_init_rtc(void);
extern unsigned long est_cycle_freq;

/* smc37c93x.c */
extern void SMC93x_Init(void);

/* smc37c669.c */
extern void SMC669_Init(int);

/* es1888.c */
extern void es1888_init(void);

/* ../lib/fpreg.c */
extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
extern unsigned long alpha_read_fp_reg (unsigned long reg);

/* head.S */
extern void wrmces(unsigned long mces);
extern void cserve_ena(unsigned long);
extern void cserve_dis(unsigned long);
extern void __smp_callin(unsigned long);

/* entry.S */
extern void entArith(void);
extern void entIF(void);
extern void entInt(void);
extern void entMM(void);
extern void entSys(void);
extern void entUna(void);
extern void entDbg(void);

/* ptrace.c */
extern int ptrace_set_bpt (struct task_struct *child);
extern int ptrace_cancel_bpt (struct task_struct *child);

/* traps.c */
extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15);
extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);

/* sys_titan.c */
extern void titan_dispatch_irqs(u64);

/* ../mm/init.c */
extern void switch_to_system_map(void);
extern void srm_paging_stop(void);

static inline int
__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
			 unsigned long size, unsigned long flags)
{
	pgprot_t prot;

	prot = __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE
			| _PAGE_KWE | flags);
	return ioremap_page_range(address, address + size, phys_addr, prot);
}

/* irq.c */

#ifdef CONFIG_SMP
#define mcheck_expected(cpu)	(cpu_data[cpu].mcheck_expected)
#define mcheck_taken(cpu)	(cpu_data[cpu].mcheck_taken)
#define mcheck_extra(cpu)	(cpu_data[cpu].mcheck_extra)
#else
extern struct mcheck_info
{
	unsigned char expected __attribute__((aligned(8)));
	unsigned char taken;
	unsigned char extra;
} __mcheck_info;

#define mcheck_expected(cpu)	(*((void)(cpu), &__mcheck_info.expected))
#define mcheck_taken(cpu)	(*((void)(cpu), &__mcheck_info.taken))
#define mcheck_extra(cpu)	(*((void)(cpu), &__mcheck_info.extra))
#endif

extern void process_mcheck_info(unsigned long vector, unsigned long la_ptr,
				const char *machine, int expected);


code:
// SPDX-License-Identifier: GPL-2.0
/* ptrace.c */
/* By Ross Biro 1/23/92 */
/* edited by Linus Torvalds */
/* mangled further by Bob Manson (manson@santafe.edu) */
/* more mutilation by David Mosberger (davidm@azstarnet.com) */

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched/task_stack.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/security.h>
#include <linux/signal.h>
#include <linux/audit.h>

#include <linux/uaccess.h>
#include <asm/fpu.h>

#include "proto.h"

#define DEBUG	DBG_MEM
#undef DEBUG

#ifdef DEBUG
enum {
	DBG_MEM		= (1<<0),
	DBG_BPT		= (1<<1),
	DBG_MEM_ALL	= (1<<2)
};
#define DBG(fac,args)	{if ((fac) & DEBUG) printk args;}
#else
#define DBG(fac,args)
#endif

#define BREAKINST	0x00000080	/* call_pal bpt */

/*
 * does not yet catch signals sent when the child dies.
 * in exit.c or in signal.c.
 */

/*
 * Processes always block with the following stack-layout:
 *
 *  +================================+ <---- task + 2*PAGE_SIZE
 *  | PALcode saved frame (ps, pc,   | ^
 *  | gp, a0, a1, a2)		     | |
 *  +================================+ | struct pt_regs
 *  |	        		     | |
 *  | frame generated by SAVE_ALL    | |
 *  |	        		     | v
 *  +================================+
 *  |	        		     | ^
 *  | frame saved by do_switch_stack | | struct switch_stack
 *  |	        		     | v
 *  +================================+
 */

/*
 * The following table maps a register index into the stack offset at
 * which the register is saved.  Register indices are 0-31 for integer
 * regs, 32-63 for fp regs, and 64 for the pc.  Notice that sp and
 * zero have no stack-slot and need to be treated specially (see
 * get_reg/put_reg below).
 */
enum {
	REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64
};

#define PT_REG(reg) \
  (PAGE_SIZE*2 - sizeof(struct pt_regs) + offsetof(struct pt_regs, reg))

#define SW_REG(reg) \
 (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \
  + offsetof(struct switch_stack, reg))

static int regoff[] = {
	PT_REG(	   r0), PT_REG(	   r1), PT_REG(	   r2), PT_REG(	  r3),
	PT_REG(	   r4), PT_REG(	   r5), PT_REG(	   r6), PT_REG(	  r7),
	PT_REG(	   r8), SW_REG(	   r9), SW_REG(	  r10), SW_REG(	 r11),
	SW_REG(	  r12), SW_REG(	  r13), SW_REG(	  r14), SW_REG(	 r15),
	PT_REG(	  r16), PT_REG(	  r17), PT_REG(	  r18), PT_REG(	 r19),
	PT_REG(	  r20), PT_REG(	  r21), PT_REG(	  r22), PT_REG(	 r23),
	PT_REG(	  r24), PT_REG(	  r25), PT_REG(	  r26), PT_REG(	 r27),
	PT_REG(	  r28), PT_REG(	   gp),		   -1,		   -1,
	SW_REG(fp[ 0]), SW_REG(fp[ 1]), SW_REG(fp[ 2]), SW_REG(fp[ 3]),
	SW_REG(fp[ 4]), SW_REG(fp[ 5]), SW_REG(fp[ 6]), SW_REG(fp[ 7]),
	SW_REG(fp[ 8]), SW_REG(fp[ 9]), SW_REG(fp[10]), SW_REG(fp[11]),
	SW_REG(fp[12]), SW_REG(fp[13]), SW_REG(fp[14]), SW_REG(fp[15]),
	SW_REG(fp[16]), SW_REG(fp[17]), SW_REG(fp[18]), SW_REG(fp[19]),
	SW_REG(fp[20]), SW_REG(fp[21]), SW_REG(fp[22]), SW_REG(fp[23]),
	SW_REG(fp[24]), SW_REG(fp[25]), SW_REG(fp[26]), SW_REG(fp[27]),
	SW_REG(fp[28]), SW_REG(fp[29]), SW_REG(fp[30]), SW_REG(fp[31]),
	PT_REG(	   pc)
};

static unsigned long zero;

/*
 * Get address of register REGNO in task TASK.
 */
static unsigned long *
get_reg_addr(struct task_struct * task, unsigned long regno)
{
	unsigned long *addr;

	if (regno == 30) {
		addr = &task_thread_info(task)->pcb.usp;
	} else if (regno == 65) {
		addr = &task_thread_info(task)->pcb.unique;
	} else if (regno == 31 || regno > 65) {
		zero = 0;
		addr = &zero;
	} else {
		addr = task_stack_page(task) + regoff[regno];
	}
	return addr;
}

/*
 * Get contents of register REGNO in task TASK.
 */
static unsigned long
get_reg(struct task_struct * task, unsigned long regno)
{
	/* Special hack for fpcr -- combine hardware and software bits.  */
	if (regno == 63) {
		unsigned long fpcr = *get_reg_addr(task, regno);
		unsigned long swcr
		  = task_thread_info(task)->ieee_state & IEEE_SW_MASK;
		swcr = swcr_update_status(swcr, fpcr);
		return fpcr | swcr;
	}
	return *get_reg_addr(task, regno);
}

/*
 * Write contents of register REGNO in task TASK.
 */
static int
put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
{
	if (regno == 63) {
		task_thread_info(task)->ieee_state
		  = ((task_thread_info(task)->ieee_state & ~IEEE_SW_MASK)
		     | (data & IEEE_SW_MASK));
		data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data);
	}
	*get_reg_addr(task, regno) = data;
	return 0;
}

static inline int
read_int(struct task_struct *task, unsigned long addr, int * data)
{
	int copied = access_process_vm(task, addr, data, sizeof(int),
			FOLL_FORCE);
	return (copied == sizeof(int)) ? 0 : -EIO;
}

static inline int
write_int(struct task_struct *task, unsigned long addr, int data)
{
	int copied = access_process_vm(task, addr, &data, sizeof(int),
			FOLL_FORCE | FOLL_WRITE);
	return (copied == sizeof(int)) ? 0 : -EIO;
}

/*
 * Set breakpoint.
 */
int
ptrace_set_bpt(struct task_struct * child)
{
	int displ, i, res, reg_b, nsaved = 0;
	unsigned int insn, op_code;
	unsigned long pc;

	pc  = get_reg(child, REG_PC);
	res = read_int(child, pc, (int *) &insn);
	if (res < 0)
		return res;

	op_code = insn >> 26;
	if (op_code >= 0x30) {
		/*
		 * It's a branch: instead of trying to figure out
		 * whether the branch will be taken or not, we'll put
		 * a breakpoint at either location.  This is simpler,
		 * more reliable, and probably not a whole lot slower
		 * than the alternative approach of emulating the
		 * branch (emulation can be tricky for fp branches).
		 */
		displ = ((s32)(insn << 11)) >> 9;
		task_thread_info(child)->bpt_addr[nsaved++] = pc + 4;
		if (displ)		/* guard against unoptimized code */
			task_thread_info(child)->bpt_addr[nsaved++]
			  = pc + 4 + displ;
		DBG(DBG_BPT, ("execing branch\n"));
	} else if (op_code == 0x1a) {
		reg_b = (insn >> 16) & 0x1f;
		task_thread_info(child)->bpt_addr[nsaved++] = get_reg(child, reg_b);
		DBG(DBG_BPT, ("execing jump\n"));
	} else {
		task_thread_info(child)->bpt_addr[nsaved++] = pc + 4;
		DBG(DBG_BPT, ("execing normal insn\n"));
	}

	/* install breakpoints: */
	for (i = 0; i < nsaved; ++i) {
		res = read_int(child, task_thread_info(child)->bpt_addr[i],
			       (int *) &insn);
		if (res < 0)
			return res;
		task_thread_info(child)->bpt_insn[i] = insn;
		DBG(DBG_BPT, ("    -> next_pc=%lx\n",
			      task_thread_info(child)->bpt_addr[i]));
		res = write_int(child, task_thread_info(child)->bpt_addr[i],
				BREAKINST);
		if (res < 0)
			return res;
	}
	task_thread_info(child)->bpt_nsaved = nsaved;
	return 0;
}

/*
 * Ensure no single-step breakpoint is pending.  Returns non-zero
 * value if child was being single-stepped.
 */
int
ptrace_cancel_bpt(struct task_struct * child)
{
	int i, nsaved = task_thread_info(child)->bpt_nsaved;

	task_thread_info(child)->bpt_nsaved = 0;

	if (nsaved > 2) {
		printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
		nsaved = 2;
	}

	for (i = 0; i < nsaved; ++i) {
		write_int(child, task_thread_info(child)->bpt_addr[i],
			  task_thread_info(child)->bpt_insn[i]);
	}
	return (nsaved != 0);
}

void user_enable_single_step(struct task_struct *child)
{
	/* Mark single stepping.  */
	task_thread_info(child)->bpt_nsaved = -1;
}

void user_disable_single_step(struct task_struct *child)
{
	ptrace_cancel_bpt(child);
}

/*
 * Called by kernel/ptrace.c when detaching..
 *
 * Make sure the single step bit is not set.
 */
void ptrace_disable(struct task_struct *child)
{
	user_disable_single_step(child);
}

long arch_ptrace(struct task_struct *child, long request,
		 unsigned long addr, unsigned long data)
{
	unsigned long tmp;
	size_t copied;
	long ret;

	switch (request) {
	/* When I and D space are separate, these will need to be fixed.  */
	case PTRACE_PEEKTEXT: /* read word at location addr. */
	case PTRACE_PEEKDATA:
		copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp),
				FOLL_FORCE);
		ret = -EIO;
		if (copied != sizeof(tmp))
			break;

		force_successful_syscall_return();
		ret = tmp;
		break;

	/* Read register number ADDR. */
	case PTRACE_PEEKUSR:
		force_successful_syscall_return();
		ret = get_reg(child, addr);
		DBG(DBG_MEM, ("peek $%lu->%#lx\n", addr, ret));
		break;

	/* When I and D space are separate, this will have to be fixed.  */
	case PTRACE_POKETEXT: /* write the word at location addr. */
	case PTRACE_POKEDATA:
		ret = generic_ptrace_pokedata(child, addr, data);
		break;

	case PTRACE_POKEUSR: /* write the specified register */
		DBG(DBG_MEM, ("poke $%lu<-%#lx\n", addr, data));
		ret = put_reg(child, addr, data);
		break;
	default:
		ret = ptrace_request(child, request, addr, data);
		break;
	}
	return ret;
}

asmlinkage unsigned long syscall_trace_enter(void)
{
	unsigned long ret = 0;
	struct pt_regs *regs = current_pt_regs();
	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
	    ptrace_report_syscall_entry(current_pt_regs()))
		ret = -1UL;
	audit_syscall_entry(regs->r0, regs->r16, regs->r17, regs->r18, regs->r19);
	return ret ?: current_pt_regs()->r0;
}

asmlinkage void
syscall_trace_leave(void)
{
	audit_syscall_exit(current_pt_regs());
	if (test_thread_flag(TIF_SYSCALL_TRACE))
		ptrace_report_syscall_exit(current_pt_regs(), 0);
}


code:
// SPDX-License-Identifier: GPL-2.0
/*
 *  linux/arch/alpha/kernel/rtc.c
 *
 *  Copyright (C) 1991, 1992, 1995, 1999, 2000  Linus Torvalds
 *
 * This file contains date handling.
 */
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/mc146818rtc.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>

#include "proto.h"

/*
 * Support for the RTC device.
 *
 * We don't want to use the rtc-cmos driver, because we don't want to support
 * alarms, as that would be indistinguishable from timer interrupts.
 *
 * Further, generic code is really, really tied to a 1900 epoch.  This is
 * true in __get_rtc_time as well as the users of struct rtc_time e.g.
 * rtc_tm_to_time.  Thankfully all of the other epochs in use are later
 * than 1900, and so it's easy to adjust.
 */

static unsigned long rtc_epoch;

static int __init
specifiy_epoch(char *str)
{
	unsigned long epoch = simple_strtoul(str, NULL, 0);
	if (epoch < 1900)
		printk("Ignoring invalid user specified epoch %lu\n", epoch);
	else
		rtc_epoch = epoch;
	return 1;
}
__setup("epoch=", specifiy_epoch);

static void __init
init_rtc_epoch(void)
{
	int epoch, year, ctrl;

	if (rtc_epoch != 0) {
		/* The epoch was specified on the command-line.  */
		return;
	}

	/* Detect the epoch in use on this computer.  */
	ctrl = CMOS_READ(RTC_CONTROL);
	year = CMOS_READ(RTC_YEAR);
	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
		year = bcd2bin(year);

	/* PC-like is standard; used for year >= 70 */
	epoch = 1900;
	if (year < 20) {
		epoch = 2000;
	} else if (year >= 20 && year < 48) {
		/* NT epoch */
		epoch = 1980;
	} else if (year >= 48 && year < 70) {
		/* Digital UNIX epoch */
		epoch = 1952;
	}
	rtc_epoch = epoch;

	printk(KERN_INFO "Using epoch %d for rtc year %d\n", epoch, year);
}

static int
alpha_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	int ret = mc146818_get_time(tm);

	if (ret < 0) {
		dev_err_ratelimited(dev, "unable to read current time\n");
		return ret;
	}

	/* Adjust for non-default epochs.  It's easier to depend on the
	   generic __get_rtc_time and adjust the epoch here than create
	   a copy of __get_rtc_time with the edits we need.  */
	if (rtc_epoch != 1900) {
		int year = tm->tm_year;
		/* Undo the century adjustment made in __get_rtc_time.  */
		if (year >= 100)
			year -= 100;
		year += rtc_epoch - 1900;
		/* Redo the century adjustment with the epoch in place.  */
		if (year <= 69)
			year += 100;
		tm->tm_year = year;
	}

	return 0;
}

static int
alpha_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct rtc_time xtm;

	if (rtc_epoch != 1900) {
		xtm = *tm;
		xtm.tm_year -= rtc_epoch - 1900;
		tm = &xtm;
	}

	return mc146818_set_time(tm);
}

static int
alpha_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
	switch (cmd) {
	case RTC_EPOCH_READ:
		return put_user(rtc_epoch, (unsigned long __user *)arg);
	case RTC_EPOCH_SET:
		if (arg < 1900)
			return -EINVAL;
		rtc_epoch = arg;
		return 0;
	default:
		return -ENOIOCTLCMD;
	}
}

static const struct rtc_class_ops alpha_rtc_ops = {
	.read_time = alpha_rtc_read_time,
	.set_time = alpha_rtc_set_time,
	.ioctl = alpha_rtc_ioctl,
};

/*
 * Similarly, except do the actual CMOS access on the boot cpu only.
 * This requires marshalling the data across an interprocessor call.
 */

#if defined(CONFIG_SMP) && \
    (defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_MARVEL))
# define HAVE_REMOTE_RTC 1

union remote_data {
	struct rtc_time *tm;
	long retval;
};

static void
do_remote_read(void *data)
{
	union remote_data *x = data;
	x->retval = alpha_rtc_read_time(NULL, x->tm);
}

static int
remote_read_time(struct device *dev, struct rtc_time *tm)
{
	union remote_data x;
	if (smp_processor_id() != boot_cpuid) {
		x.tm = tm;
		smp_call_function_single(boot_cpuid, do_remote_read, &x, 1);
		return x.retval;
	}
	return alpha_rtc_read_time(NULL, tm);
}

static void
do_remote_set(void *data)
{
	union remote_data *x = data;
	x->retval = alpha_rtc_set_time(NULL, x->tm);
}

static int
remote_set_time(struct device *dev, struct rtc_time *tm)
{
	union remote_data x;
	if (smp_processor_id() != boot_cpuid) {
		x.tm = tm;
		smp_call_function_single(boot_cpuid, do_remote_set, &x, 1);
		return x.retval;
	}
	return alpha_rtc_set_time(NULL, tm);
}

static const struct rtc_class_ops remote_rtc_ops = {
	.read_time = remote_read_time,
	.set_time = remote_set_time,
	.ioctl = alpha_rtc_ioctl,
};
#endif

static int __init
alpha_rtc_init(void)
{
	struct platform_device *pdev;
	struct rtc_device *rtc;

	init_rtc_epoch();

	pdev = platform_device_register_simple("rtc-alpha", -1, NULL, 0);
	rtc = devm_rtc_allocate_device(&pdev->dev);
	if (IS_ERR(rtc))
		return PTR_ERR(rtc);

	platform_set_drvdata(pdev, rtc);
	rtc->ops = &alpha_rtc_ops;

#ifdef HAVE_REMOTE_RTC
	if (alpha_mv.rtc_boot_cpu_only)
		rtc->ops = &remote_rtc_ops;
#endif

	return devm_rtc_register_device(rtc);
}
device_initcall(alpha_rtc_init);