You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: (230 commits) [SPARC64]: Update defconfig. [SPARC64]: Fix 2 bugs in huge page support. [SPARC64]: CONFIG_BLK_DEV_RAM fix [SPARC64]: Optimized TSB table initialization. [SPARC64]: Allow CONFIG_MEMORY_HOTPLUG to build. [SPARC64]: Use SLAB caches for TSB tables. [SPARC64]: Don't kill the page allocator when growing a TSB. [SPARC64]: Randomize mm->mmap_base when PF_RANDOMIZE is set. [SPARC64]: Increase top of 32-bit process stack. [SPARC64]: Top-down address space allocation for 32-bit tasks. [SPARC64] bbc_i2c: Fix cpu check and add missing module license. [SPARC64]: Fix and re-enable dynamic TSB sizing. [SUNSU]: Fix missing spinlock initialization. [TG3]: Do not try to access NIC_SRAM_DATA_SIG on Sun parts. [SPARC64]: First cut at VIS simulator for Niagara. [SPARC64]: Fix system type in /proc/cpuinfo and remove bogus OBP check. [SPARC64]: Add SMT scheduling support for Niagara. [SPARC64]: Fix 32-bit truncation which broke sparsemem. [SPARC64]: Move over to sparsemem. [SPARC64]: Fix new context version SMP handling. ...
This commit is contained in:
+15
-25
@@ -217,7 +217,7 @@ static void _sparc_free_io(struct resource *res)
|
||||
unsigned long plen;
|
||||
|
||||
plen = res->end - res->start + 1;
|
||||
if ((plen & (PAGE_SIZE-1)) != 0) BUG();
|
||||
BUG_ON((plen & (PAGE_SIZE-1)) != 0);
|
||||
sparc_unmapiorange(res->start, plen);
|
||||
release_resource(res);
|
||||
}
|
||||
@@ -512,8 +512,7 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
|
||||
dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size,
|
||||
int direction)
|
||||
{
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
/* IIep is write-through, not flushing. */
|
||||
return virt_to_phys(ptr);
|
||||
}
|
||||
@@ -528,8 +527,7 @@ dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size,
|
||||
void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size,
|
||||
int direction)
|
||||
{
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
if (direction != PCI_DMA_TODEVICE) {
|
||||
mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
|
||||
(size + PAGE_SIZE-1) & PAGE_MASK);
|
||||
@@ -542,8 +540,7 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size,
|
||||
dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
|
||||
unsigned long offset, size_t size, int direction)
|
||||
{
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
/* IIep is write-through, not flushing. */
|
||||
return page_to_phys(page) + offset;
|
||||
}
|
||||
@@ -551,8 +548,7 @@ dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
|
||||
void pci_unmap_page(struct pci_dev *hwdev,
|
||||
dma_addr_t dma_address, size_t size, int direction)
|
||||
{
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
/* mmu_inval_dma_area XXX */
|
||||
}
|
||||
|
||||
@@ -576,11 +572,10 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
|
||||
{
|
||||
int n;
|
||||
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
/* IIep is write-through, not flushing. */
|
||||
for (n = 0; n < nents; n++) {
|
||||
if (page_address(sg->page) == NULL) BUG();
|
||||
BUG_ON(page_address(sg->page) == NULL);
|
||||
sg->dvma_address = virt_to_phys(page_address(sg->page));
|
||||
sg->dvma_length = sg->length;
|
||||
sg++;
|
||||
@@ -597,11 +592,10 @@ void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
|
||||
{
|
||||
int n;
|
||||
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
if (direction != PCI_DMA_TODEVICE) {
|
||||
for (n = 0; n < nents; n++) {
|
||||
if (page_address(sg->page) == NULL) BUG();
|
||||
BUG_ON(page_address(sg->page) == NULL);
|
||||
mmu_inval_dma_area(
|
||||
(unsigned long) page_address(sg->page),
|
||||
(sg->length + PAGE_SIZE-1) & PAGE_MASK);
|
||||
@@ -622,8 +616,7 @@ void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents,
|
||||
*/
|
||||
void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t ba, size_t size, int direction)
|
||||
{
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
if (direction != PCI_DMA_TODEVICE) {
|
||||
mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
|
||||
(size + PAGE_SIZE-1) & PAGE_MASK);
|
||||
@@ -632,8 +625,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t ba, size_t si
|
||||
|
||||
void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t ba, size_t size, int direction)
|
||||
{
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
if (direction != PCI_DMA_TODEVICE) {
|
||||
mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
|
||||
(size + PAGE_SIZE-1) & PAGE_MASK);
|
||||
@@ -650,11 +642,10 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int
|
||||
{
|
||||
int n;
|
||||
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
if (direction != PCI_DMA_TODEVICE) {
|
||||
for (n = 0; n < nents; n++) {
|
||||
if (page_address(sg->page) == NULL) BUG();
|
||||
BUG_ON(page_address(sg->page) == NULL);
|
||||
mmu_inval_dma_area(
|
||||
(unsigned long) page_address(sg->page),
|
||||
(sg->length + PAGE_SIZE-1) & PAGE_MASK);
|
||||
@@ -667,11 +658,10 @@ void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg, i
|
||||
{
|
||||
int n;
|
||||
|
||||
if (direction == PCI_DMA_NONE)
|
||||
BUG();
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
if (direction != PCI_DMA_TODEVICE) {
|
||||
for (n = 0; n < nents; n++) {
|
||||
if (page_address(sg->page) == NULL) BUG();
|
||||
BUG_ON(page_address(sg->page) == NULL);
|
||||
mmu_inval_dma_area(
|
||||
(unsigned long) page_address(sg->page),
|
||||
(sg->length + PAGE_SIZE-1) & PAGE_MASK);
|
||||
|
||||
@@ -186,6 +186,15 @@ endchoice
|
||||
|
||||
endmenu
|
||||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
def_bool y
|
||||
|
||||
config ARCH_SPARSEMEM_DEFAULT
|
||||
def_bool y
|
||||
|
||||
config LARGE_ALLOCS
|
||||
def_bool y
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
config GENERIC_ISA_DMA
|
||||
@@ -350,6 +359,15 @@ config SOLARIS_EMUL
|
||||
|
||||
endmenu
|
||||
|
||||
config SCHED_SMT
|
||||
bool "SMT (Hyperthreading) scheduler support"
|
||||
depends on SMP
|
||||
default y
|
||||
help
|
||||
SMT scheduler support improves the CPU scheduler's decision making
|
||||
when dealing with UltraSPARC cpus at a cost of slightly increased
|
||||
overhead in some places. If unsure say N here.
|
||||
|
||||
config CMDLINE_BOOL
|
||||
bool "Default bootloader kernel arguments"
|
||||
|
||||
|
||||
+14
-11
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.16-rc2
|
||||
# Tue Feb 7 17:47:18 2006
|
||||
# Linux kernel version: 2.6.16
|
||||
# Mon Mar 20 01:23:21 2006
|
||||
#
|
||||
CONFIG_SPARC=y
|
||||
CONFIG_SPARC64=y
|
||||
@@ -115,14 +115,20 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
|
||||
CONFIG_HUGETLB_PAGE_SIZE_4MB=y
|
||||
# CONFIG_HUGETLB_PAGE_SIZE_512K is not set
|
||||
# CONFIG_HUGETLB_PAGE_SIZE_64K is not set
|
||||
CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
||||
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
|
||||
CONFIG_LARGE_ALLOCS=y
|
||||
CONFIG_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_FLATMEM_MANUAL=y
|
||||
# CONFIG_FLATMEM_MANUAL is not set
|
||||
# CONFIG_DISCONTIGMEM_MANUAL is not set
|
||||
# CONFIG_SPARSEMEM_MANUAL is not set
|
||||
CONFIG_FLATMEM=y
|
||||
CONFIG_FLAT_NODE_MEM_MAP=y
|
||||
CONFIG_SPARSEMEM_MANUAL=y
|
||||
CONFIG_SPARSEMEM=y
|
||||
CONFIG_HAVE_MEMORY_PRESENT=y
|
||||
# CONFIG_SPARSEMEM_STATIC is not set
|
||||
CONFIG_SPARSEMEM_EXTREME=y
|
||||
CONFIG_MEMORY_HOTPLUG=y
|
||||
CONFIG_SPLIT_PTLOCK_CPUS=4
|
||||
CONFIG_MIGRATION=y
|
||||
CONFIG_GENERIC_ISA_DMA=y
|
||||
CONFIG_SBUS=y
|
||||
CONFIG_SBUSCHAR=y
|
||||
@@ -655,6 +661,7 @@ CONFIG_SERIAL_SUNCORE=y
|
||||
CONFIG_SERIAL_SUNSU=y
|
||||
CONFIG_SERIAL_SUNSU_CONSOLE=y
|
||||
CONFIG_SERIAL_SUNSAB=m
|
||||
CONFIG_SERIAL_SUNHV=y
|
||||
CONFIG_SERIAL_CORE=y
|
||||
CONFIG_SERIAL_CORE_CONSOLE=y
|
||||
# CONFIG_SERIAL_JSM is not set
|
||||
@@ -1116,11 +1123,7 @@ CONFIG_USB_HIDDEV=y
|
||||
# CONFIG_INFINIBAND is not set
|
||||
|
||||
#
|
||||
# SN Devices
|
||||
#
|
||||
|
||||
#
|
||||
# EDAC - error detection and reporting (RAS)
|
||||
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
|
||||
#
|
||||
|
||||
#
|
||||
|
||||
@@ -11,10 +11,12 @@ obj-y := process.o setup.o cpu.o idprom.o \
|
||||
traps.o devices.o auxio.o una_asm.o \
|
||||
irq.o ptrace.o time.o sys_sparc.o signal.o \
|
||||
unaligned.o central.o pci.o starfire.o semaphore.o \
|
||||
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o
|
||||
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
|
||||
visemul.o
|
||||
|
||||
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
|
||||
pci_psycho.o pci_sabre.o pci_schizo.o
|
||||
pci_psycho.o pci_sabre.o pci_schizo.o \
|
||||
pci_sun4v.o pci_sun4v_asm.o
|
||||
obj-$(CONFIG_SMP) += smp.o trampoline.o
|
||||
obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o
|
||||
obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o
|
||||
@@ -38,5 +40,5 @@ else
|
||||
CMODEL_CFLAG := -m64 -mcmodel=medlow
|
||||
endif
|
||||
|
||||
head.o: head.S ttable.S itlb_base.S dtlb_base.S dtlb_backend.S dtlb_prot.S \
|
||||
head.o: head.S ttable.S itlb_miss.S dtlb_miss.S ktlb.S tsb.S \
|
||||
etrap.S rtrap.S winfixup.S entry.S
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
||||
static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs);
|
||||
static int load_aout32_library(struct file*);
|
||||
@@ -238,6 +239,8 @@ static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs)
|
||||
(current->mm->start_data = N_DATADDR(ex));
|
||||
current->mm->brk = ex.a_bss +
|
||||
(current->mm->start_brk = N_BSSADDR(ex));
|
||||
current->mm->free_area_cache = current->mm->mmap_base;
|
||||
current->mm->cached_hole_size = 0;
|
||||
|
||||
current->mm->mmap = NULL;
|
||||
compute_creds(bprm);
|
||||
@@ -329,15 +332,8 @@ beyond_if:
|
||||
|
||||
current->mm->start_stack =
|
||||
(unsigned long) create_aout32_tables((char __user *)bprm->p, bprm);
|
||||
if (!(orig_thr_flags & _TIF_32BIT)) {
|
||||
unsigned long pgd_cache = get_pgd_cache(current->mm->pgd);
|
||||
tsb_context_switch(current->mm);
|
||||
|
||||
__asm__ __volatile__("stxa\t%0, [%1] %2\n\t"
|
||||
"membar #Sync"
|
||||
: /* no outputs */
|
||||
: "r" (pgd_cache),
|
||||
"r" (TSB_REG), "i" (ASI_DMMU));
|
||||
}
|
||||
start_thread32(regs, ex.a_entry, current->mm->start_stack);
|
||||
if (current->ptrace & PT_PTRACED)
|
||||
send_sig(SIGTRAP, current, 0);
|
||||
|
||||
@@ -153,7 +153,9 @@ MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek");
|
||||
#undef MODULE_DESCRIPTION
|
||||
#undef MODULE_AUTHOR
|
||||
|
||||
#include <asm/a.out.h>
|
||||
|
||||
#undef TASK_SIZE
|
||||
#define TASK_SIZE 0xf0000000
|
||||
#define TASK_SIZE STACK_TOP32
|
||||
|
||||
#include "../../../fs/binfmt_elf.c"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/fpumacro.h>
|
||||
#include <asm/cpudata.h>
|
||||
#include <asm/spitfire.h>
|
||||
|
||||
DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };
|
||||
|
||||
@@ -71,6 +72,12 @@ void __init cpu_probe(void)
|
||||
unsigned long ver, fpu_vers, manuf, impl, fprs;
|
||||
int i;
|
||||
|
||||
if (tlb_type == hypervisor) {
|
||||
sparc_cpu_type = "UltraSparc T1 (Niagara)";
|
||||
sparc_fpu_type = "UltraSparc T1 integrated FPU";
|
||||
return;
|
||||
}
|
||||
|
||||
fprs = fprs_read();
|
||||
fprs_write(FPRS_FEF);
|
||||
__asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]"
|
||||
|
||||
+179
-10
@@ -12,6 +12,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/oplib.h>
|
||||
@@ -20,6 +21,8 @@
|
||||
#include <asm/spitfire.h>
|
||||
#include <asm/timer.h>
|
||||
#include <asm/cpudata.h>
|
||||
#include <asm/vdev.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/* Used to synchronize acceses to NatSemi SUPER I/O chip configure
|
||||
* operations in asm/ns87303.h
|
||||
@@ -29,13 +32,158 @@ DEFINE_SPINLOCK(ns87303_lock);
|
||||
extern void cpu_probe(void);
|
||||
extern void central_probe(void);
|
||||
|
||||
static char *cpu_mid_prop(void)
|
||||
u32 sun4v_vdev_devhandle;
|
||||
int sun4v_vdev_root;
|
||||
|
||||
struct vdev_intmap {
|
||||
unsigned int phys;
|
||||
unsigned int irq;
|
||||
unsigned int cnode;
|
||||
unsigned int cinterrupt;
|
||||
};
|
||||
|
||||
struct vdev_intmask {
|
||||
unsigned int phys;
|
||||
unsigned int interrupt;
|
||||
unsigned int __unused;
|
||||
};
|
||||
|
||||
static struct vdev_intmap *vdev_intmap;
|
||||
static int vdev_num_intmap;
|
||||
static struct vdev_intmask vdev_intmask;
|
||||
|
||||
static void __init sun4v_virtual_device_probe(void)
|
||||
{
|
||||
struct linux_prom64_registers regs;
|
||||
struct vdev_intmap *ip;
|
||||
int node, sz, err;
|
||||
|
||||
if (tlb_type != hypervisor)
|
||||
return;
|
||||
|
||||
node = prom_getchild(prom_root_node);
|
||||
node = prom_searchsiblings(node, "virtual-devices");
|
||||
if (!node) {
|
||||
prom_printf("SUN4V: Fatal error, no virtual-devices node.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
sun4v_vdev_root = node;
|
||||
|
||||
prom_getproperty(node, "reg", (char *)®s, sizeof(regs));
|
||||
sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff;
|
||||
|
||||
sz = prom_getproplen(node, "interrupt-map");
|
||||
if (sz <= 0) {
|
||||
prom_printf("SUN4V: Error, no vdev interrupt-map.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
if ((sz % sizeof(*ip)) != 0) {
|
||||
prom_printf("SUN4V: Bogus interrupt-map property size %d\n",
|
||||
sz);
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
vdev_intmap = ip = alloc_bootmem_low_pages(sz);
|
||||
if (!vdev_intmap) {
|
||||
prom_printf("SUN4V: Error, cannot allocate vdev_intmap.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
err = prom_getproperty(node, "interrupt-map", (char *) ip, sz);
|
||||
if (err == -1) {
|
||||
prom_printf("SUN4V: Fatal error, no vdev interrupt-map.\n");
|
||||
prom_halt();
|
||||
}
|
||||
if (err != sz) {
|
||||
prom_printf("SUN4V: Inconsistent interrupt-map size, "
|
||||
"proplen(%d) vs getprop(%d).\n", sz,err);
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
vdev_num_intmap = err / sizeof(*ip);
|
||||
|
||||
err = prom_getproperty(node, "interrupt-map-mask",
|
||||
(char *) &vdev_intmask,
|
||||
sizeof(vdev_intmask));
|
||||
if (err <= 0) {
|
||||
prom_printf("SUN4V: Fatal error, no vdev "
|
||||
"interrupt-map-mask.\n");
|
||||
prom_halt();
|
||||
}
|
||||
if (err % sizeof(vdev_intmask)) {
|
||||
prom_printf("SUN4V: Bogus interrupt-map-mask "
|
||||
"property size %d\n", err);
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
printk("SUN4V: virtual-devices devhandle[%x]\n",
|
||||
sun4v_vdev_devhandle);
|
||||
}
|
||||
|
||||
unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
|
||||
{
|
||||
unsigned int irq, reg;
|
||||
int err, i;
|
||||
|
||||
err = prom_getproperty(dev_node, "interrupts",
|
||||
(char *) &irq, sizeof(irq));
|
||||
if (err <= 0) {
|
||||
printk("VDEV: Cannot get \"interrupts\" "
|
||||
"property for OBP node %x\n", dev_node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = prom_getproperty(dev_node, "reg",
|
||||
(char *) ®, sizeof(reg));
|
||||
if (err <= 0) {
|
||||
printk("VDEV: Cannot get \"reg\" "
|
||||
"property for OBP node %x\n", dev_node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < vdev_num_intmap; i++) {
|
||||
if (vdev_intmap[i].phys == (reg & vdev_intmask.phys) &&
|
||||
vdev_intmap[i].irq == (irq & vdev_intmask.interrupt)) {
|
||||
irq = vdev_intmap[i].cinterrupt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == vdev_num_intmap) {
|
||||
printk("VDEV: No matching interrupt map entry "
|
||||
"for OBP node %x\n", dev_node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0);
|
||||
}
|
||||
|
||||
static const char *cpu_mid_prop(void)
|
||||
{
|
||||
if (tlb_type == spitfire)
|
||||
return "upa-portid";
|
||||
return "portid";
|
||||
}
|
||||
|
||||
static int get_cpu_mid(int prom_node)
|
||||
{
|
||||
if (tlb_type == hypervisor) {
|
||||
struct linux_prom64_registers reg;
|
||||
|
||||
if (prom_getproplen(prom_node, "cpuid") == 4)
|
||||
return prom_getintdefault(prom_node, "cpuid", 0);
|
||||
|
||||
prom_getproperty(prom_node, "reg", (char *) ®, sizeof(reg));
|
||||
return (reg.phys_addr >> 32) & 0x0fffffffUL;
|
||||
} else {
|
||||
const char *prop_name = cpu_mid_prop();
|
||||
|
||||
return prom_getintdefault(prom_node, prop_name, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int check_cpu_node(int nd, int *cur_inst,
|
||||
int (*compare)(int, int, void *), void *compare_arg,
|
||||
int *prom_node, int *mid)
|
||||
@@ -50,7 +198,7 @@ static int check_cpu_node(int nd, int *cur_inst,
|
||||
if (prom_node)
|
||||
*prom_node = nd;
|
||||
if (mid)
|
||||
*mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
|
||||
*mid = get_cpu_mid(nd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -105,7 +253,7 @@ static int cpu_mid_compare(int nd, int instance, void *_arg)
|
||||
int desired_mid = (int) (long) _arg;
|
||||
int this_mid;
|
||||
|
||||
this_mid = prom_getintdefault(nd, cpu_mid_prop(), 0);
|
||||
this_mid = get_cpu_mid(nd);
|
||||
if (this_mid == desired_mid)
|
||||
return 0;
|
||||
return -ENODEV;
|
||||
@@ -126,7 +274,8 @@ void __init device_scan(void)
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
{
|
||||
int err, cpu_node;
|
||||
int err, cpu_node, def;
|
||||
|
||||
err = cpu_find_by_instance(0, &cpu_node, NULL);
|
||||
if (err) {
|
||||
prom_printf("No cpu nodes, cannot continue\n");
|
||||
@@ -135,21 +284,40 @@ void __init device_scan(void)
|
||||
cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
|
||||
"clock-frequency",
|
||||
0);
|
||||
|
||||
def = ((tlb_type == hypervisor) ?
|
||||
(8 * 1024) :
|
||||
(16 * 1024));
|
||||
cpu_data(0).dcache_size = prom_getintdefault(cpu_node,
|
||||
"dcache-size",
|
||||
16 * 1024);
|
||||
def);
|
||||
|
||||
def = 32;
|
||||
cpu_data(0).dcache_line_size =
|
||||
prom_getintdefault(cpu_node, "dcache-line-size", 32);
|
||||
prom_getintdefault(cpu_node, "dcache-line-size",
|
||||
def);
|
||||
|
||||
def = 16 * 1024;
|
||||
cpu_data(0).icache_size = prom_getintdefault(cpu_node,
|
||||
"icache-size",
|
||||
16 * 1024);
|
||||
def);
|
||||
|
||||
def = 32;
|
||||
cpu_data(0).icache_line_size =
|
||||
prom_getintdefault(cpu_node, "icache-line-size", 32);
|
||||
prom_getintdefault(cpu_node, "icache-line-size",
|
||||
def);
|
||||
|
||||
def = ((tlb_type == hypervisor) ?
|
||||
(3 * 1024 * 1024) :
|
||||
(4 * 1024 * 1024));
|
||||
cpu_data(0).ecache_size = prom_getintdefault(cpu_node,
|
||||
"ecache-size",
|
||||
4 * 1024 * 1024);
|
||||
def);
|
||||
|
||||
def = 64;
|
||||
cpu_data(0).ecache_line_size =
|
||||
prom_getintdefault(cpu_node, "ecache-line-size", 64);
|
||||
prom_getintdefault(cpu_node, "ecache-line-size",
|
||||
def);
|
||||
printk("CPU[0]: Caches "
|
||||
"D[sz(%d):line_sz(%d)] "
|
||||
"I[sz(%d):line_sz(%d)] "
|
||||
@@ -160,6 +328,7 @@ void __init device_scan(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
sun4v_virtual_device_probe();
|
||||
central_probe();
|
||||
|
||||
cpu_probe();
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
/* $Id: dtlb_backend.S,v 1.16 2001/10/09 04:02:11 davem Exp $
|
||||
* dtlb_backend.S: Back end to DTLB miss replacement strategy.
|
||||
* This is included directly into the trap table.
|
||||
*
|
||||
* Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
|
||||
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
|
||||
*/
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
#define VALID_SZ_BITS (_PAGE_VALID | _PAGE_SZBITS)
|
||||
|
||||
#define VPTE_BITS (_PAGE_CP | _PAGE_CV | _PAGE_P )
|
||||
#define VPTE_SHIFT (PAGE_SHIFT - 3)
|
||||
|
||||
/* Ways we can get here:
|
||||
*
|
||||
* 1) Nucleus loads and stores to/from PA-->VA direct mappings at tl>1.
|
||||
* 2) Nucleus loads and stores to/from user/kernel window save areas.
|
||||
* 3) VPTE misses from dtlb_base and itlb_base.
|
||||
*
|
||||
* We need to extract out the PMD and PGDIR indexes from the
|
||||
* linear virtual page table access address. The PTE index
|
||||
* is at the bottom, but we are not concerned with it. Bits
|
||||
* 0 to 2 are clear since each PTE is 8 bytes in size. Each
|
||||
* PMD and PGDIR entry are 4 bytes in size. Thus, this
|
||||
* address looks something like:
|
||||
*
|
||||
* |---------------------------------------------------------------|
|
||||
* | ... | PGDIR index | PMD index | PTE index | |
|
||||
* |---------------------------------------------------------------|
|
||||
* 63 F E D C B A 3 2 0 <- bit nr
|
||||
*
|
||||
* The variable bits above are defined as:
|
||||
* A --> 3 + (PAGE_SHIFT - log2(8))
|
||||
* --> 3 + (PAGE_SHIFT - 3) - 1
|
||||
* (ie. this is "bit 3" + PAGE_SIZE - size of PTE entry in bits - 1)
|
||||
* B --> A + 1
|
||||
* C --> B + (PAGE_SHIFT - log2(4))
|
||||
* --> B + (PAGE_SHIFT - 2) - 1
|
||||
* (ie. this is "bit B" + PAGE_SIZE - size of PMD entry in bits - 1)
|
||||
* D --> C + 1
|
||||
* E --> D + (PAGE_SHIFT - log2(4))
|
||||
* --> D + (PAGE_SHIFT - 2) - 1
|
||||
* (ie. this is "bit D" + PAGE_SIZE - size of PGDIR entry in bits - 1)
|
||||
* F --> E + 1
|
||||
*
|
||||
* (Note how "B" always evalutes to PAGE_SHIFT, all the other constants
|
||||
* cancel out.)
|
||||
*
|
||||
* For 8K PAGE_SIZE (thus, PAGE_SHIFT of 13) the bit numbers are:
|
||||
* A --> 12
|
||||
* B --> 13
|
||||
* C --> 23
|
||||
* D --> 24
|
||||
* E --> 34
|
||||
* F --> 35
|
||||
*
|
||||
* For 64K PAGE_SIZE (thus, PAGE_SHIFT of 16) the bit numbers are:
|
||||
* A --> 15
|
||||
* B --> 16
|
||||
* C --> 29
|
||||
* D --> 30
|
||||
* E --> 43
|
||||
* F --> 44
|
||||
*
|
||||
* Because bits both above and below each PGDIR and PMD index need to
|
||||
* be masked out, and the index can be as long as 14 bits (when using a
|
||||
* 64K PAGE_SIZE, and thus a PAGE_SHIFT of 16), we need 3 instructions
|
||||
* to extract each index out.
|
||||
*
|
||||
* Shifts do not pair very well on UltraSPARC-I, II, IIi, and IIe, so
|
||||
* we try to avoid using them for the entire operation. We could setup
|
||||
* a mask anywhere from bit 31 down to bit 10 using the sethi instruction.
|
||||
*
|
||||
* We need a mask covering bits B --> C and one covering D --> E.
|
||||
* For 8K PAGE_SIZE these masks are 0x00ffe000 and 0x7ff000000.
|
||||
* For 64K PAGE_SIZE these masks are 0x3fff0000 and 0xfffc0000000.
|
||||
* The second in each set cannot be loaded with a single sethi
|
||||
* instruction, because the upper bits are past bit 32. We would
|
||||
* need to use a sethi + a shift.
|
||||
*
|
||||
* For the time being, we use 2 shifts and a simple "and" mask.
|
||||
* We shift left to clear the bits above the index, we shift down
|
||||
* to clear the bits below the index (sans the log2(4 or 8) bits)
|
||||
* and a mask to clear the log2(4 or 8) bits. We need therefore
|
||||
* define 4 shift counts, all of which are relative to PAGE_SHIFT.
|
||||
*
|
||||
* Although unsupportable for other reasons, this does mean that
|
||||
* 512K and 4MB page sizes would be generaally supported by the
|
||||
* kernel. (ELF binaries would break with > 64K PAGE_SIZE since
|
||||
* the sections are only aligned that strongly).
|
||||
*
|
||||
* The operations performed for extraction are thus:
|
||||
*
|
||||
* ((X << FOO_SHIFT_LEFT) >> FOO_SHIFT_RIGHT) & ~0x3
|
||||
*
|
||||
*/
|
||||
|
||||
#define A (3 + (PAGE_SHIFT - 3) - 1)
|
||||
#define B (A + 1)
|
||||
#define C (B + (PAGE_SHIFT - 2) - 1)
|
||||
#define D (C + 1)
|
||||
#define E (D + (PAGE_SHIFT - 2) - 1)
|
||||
#define F (E + 1)
|
||||
|
||||
#define PMD_SHIFT_LEFT (64 - D)
|
||||
#define PMD_SHIFT_RIGHT (64 - (D - B) - 2)
|
||||
#define PGDIR_SHIFT_LEFT (64 - F)
|
||||
#define PGDIR_SHIFT_RIGHT (64 - (F - D) - 2)
|
||||
#define LOW_MASK_BITS 0x3
|
||||
|
||||
/* TLB1 ** ICACHE line 1: tl1 DTLB and quick VPTE miss */
|
||||
ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS
|
||||
add %g3, %g3, %g5 ! Compute VPTE base
|
||||
cmp %g4, %g5 ! VPTE miss?
|
||||
bgeu,pt %xcc, 1f ! Continue here
|
||||
andcc %g4, TAG_CONTEXT_BITS, %g5 ! tl0 miss Nucleus test
|
||||
ba,a,pt %xcc, from_tl1_trap ! Fall to tl0 miss
|
||||
1: sllx %g6, VPTE_SHIFT, %g4 ! Position TAG_ACCESS
|
||||
or %g4, %g5, %g4 ! Prepare TAG_ACCESS
|
||||
|
||||
/* TLB1 ** ICACHE line 2: Quick VPTE miss */
|
||||
mov TSB_REG, %g1 ! Grab TSB reg
|
||||
ldxa [%g1] ASI_DMMU, %g5 ! Doing PGD caching?
|
||||
sllx %g6, PMD_SHIFT_LEFT, %g1 ! Position PMD offset
|
||||
be,pn %xcc, sparc64_vpte_nucleus ! Is it from Nucleus?
|
||||
srlx %g1, PMD_SHIFT_RIGHT, %g1 ! Mask PMD offset bits
|
||||
brnz,pt %g5, sparc64_vpte_continue ! Yep, go like smoke
|
||||
andn %g1, LOW_MASK_BITS, %g1 ! Final PMD mask
|
||||
sllx %g6, PGDIR_SHIFT_LEFT, %g5 ! Position PGD offset
|
||||
|
||||
/* TLB1 ** ICACHE line 3: Quick VPTE miss */
|
||||
srlx %g5, PGDIR_SHIFT_RIGHT, %g5 ! Mask PGD offset bits
|
||||
andn %g5, LOW_MASK_BITS, %g5 ! Final PGD mask
|
||||
lduwa [%g7 + %g5] ASI_PHYS_USE_EC, %g5! Load PGD
|
||||
brz,pn %g5, vpte_noent ! Valid?
|
||||
sparc64_kpte_continue:
|
||||
sllx %g5, 11, %g5 ! Shift into place
|
||||
sparc64_vpte_continue:
|
||||
lduwa [%g5 + %g1] ASI_PHYS_USE_EC, %g5! Load PMD
|
||||
sllx %g5, 11, %g5 ! Shift into place
|
||||
brz,pn %g5, vpte_noent ! Valid?
|
||||
|
||||
/* TLB1 ** ICACHE line 4: Quick VPTE miss */
|
||||
mov (VALID_SZ_BITS >> 61), %g1 ! upper vpte into %g1
|
||||
sllx %g1, 61, %g1 ! finish calc
|
||||
or %g5, VPTE_BITS, %g5 ! Prepare VPTE data
|
||||
or %g5, %g1, %g5 ! ...
|
||||
mov TLB_SFSR, %g1 ! Restore %g1 value
|
||||
stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Load VPTE into TLB
|
||||
stxa %g4, [%g1 + %g1] ASI_DMMU ! Restore previous TAG_ACCESS
|
||||
retry ! Load PTE once again
|
||||
|
||||
#undef VALID_SZ_BITS
|
||||
#undef VPTE_SHIFT
|
||||
#undef VPTE_BITS
|
||||
#undef A
|
||||
#undef B
|
||||
#undef C
|
||||
#undef D
|
||||
#undef E
|
||||
#undef F
|
||||
#undef PMD_SHIFT_LEFT
|
||||
#undef PMD_SHIFT_RIGHT
|
||||
#undef PGDIR_SHIFT_LEFT
|
||||
#undef PGDIR_SHIFT_RIGHT
|
||||
#undef LOW_MASK_BITS
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/* $Id: dtlb_base.S,v 1.17 2001/10/11 22:33:52 davem Exp $
|
||||
* dtlb_base.S: Front end to DTLB miss replacement strategy.
|
||||
* This is included directly into the trap table.
|
||||
*
|
||||
* Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
|
||||
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
|
||||
*/
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
/* %g1 TLB_SFSR (%g1 + %g1 == TLB_TAG_ACCESS)
|
||||
* %g2 (KERN_HIGHBITS | KERN_LOWBITS)
|
||||
* %g3 VPTE base (0xfffffffe00000000) Spitfire/Blackbird (44-bit VA space)
|
||||
* (0xffe0000000000000) Cheetah (64-bit VA space)
|
||||
* %g7 __pa(current->mm->pgd)
|
||||
*
|
||||
* The VPTE base value is completely magic, but note that
|
||||
* few places in the kernel other than these TLB miss
|
||||
* handlers know anything about the VPTE mechanism or
|
||||
* how it works (see VPTE_SIZE, TASK_SIZE and PTRS_PER_PGD).
|
||||
* Consider the 44-bit VADDR Ultra-I/II case as an example:
|
||||
*
|
||||
* VA[0 : (1<<43)] produce VPTE index [%g3 : 0]
|
||||
* VA[0 : -(1<<43)] produce VPTE index [%g3-(1<<(43-PAGE_SHIFT+3)) : %g3]
|
||||
*
|
||||
* For Cheetah's 64-bit VADDR space this is:
|
||||
*
|
||||
* VA[0 : (1<<63)] produce VPTE index [%g3 : 0]
|
||||
* VA[0 : -(1<<63)] produce VPTE index [%g3-(1<<(63-PAGE_SHIFT+3)) : %g3]
|
||||
*
|
||||
* If you're paying attention you'll notice that this means half of
|
||||
* the VPTE table is above %g3 and half is below, low VA addresses
|
||||
* map progressively upwards from %g3, and high VA addresses map
|
||||
* progressively upwards towards %g3. This trick was needed to make
|
||||
* the same 8 instruction handler work both for Spitfire/Blackbird's
|
||||
* peculiar VA space hole configuration and the full 64-bit VA space
|
||||
* one of Cheetah at the same time.
|
||||
*/
|
||||
|
||||
/* Ways we can get here:
|
||||
*
|
||||
* 1) Nucleus loads and stores to/from PA-->VA direct mappings.
|
||||
* 2) Nucleus loads and stores to/from vmalloc() areas.
|
||||
* 3) User loads and stores.
|
||||
* 4) User space accesses by nucleus at tl0
|
||||
*/
|
||||
|
||||
#if PAGE_SHIFT == 13
|
||||
/*
|
||||
* To compute vpte offset, we need to do ((addr >> 13) << 3),
|
||||
* which can be optimized to (addr >> 10) if bits 10/11/12 can
|
||||
* be guaranteed to be 0 ... mmu_context.h does guarantee this
|
||||
* by only using 10 bits in the hwcontext value.
|
||||
*/
|
||||
#define CREATE_VPTE_OFFSET1(r1, r2) nop
|
||||
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
||||
srax r1, 10, r2
|
||||
#else
|
||||
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
||||
srax r1, PAGE_SHIFT, r2
|
||||
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
||||
sllx r2, 3, r2
|
||||
#endif
|
||||
|
||||
/* DTLB ** ICACHE line 1: Quick user TLB misses */
|
||||
mov TLB_SFSR, %g1
|
||||
ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Get TAG_ACCESS
|
||||
andcc %g4, TAG_CONTEXT_BITS, %g0 ! From Nucleus?
|
||||
from_tl1_trap:
|
||||
rdpr %tl, %g5 ! For TL==3 test
|
||||
CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset
|
||||
be,pn %xcc, kvmap ! Yep, special processing
|
||||
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
|
||||
cmp %g5, 4 ! Last trap level?
|
||||
|
||||
/* DTLB ** ICACHE line 2: User finish + quick kernel TLB misses */
|
||||
be,pn %xcc, longpath ! Yep, cannot risk VPTE miss
|
||||
nop ! delay slot
|
||||
ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE
|
||||
1: brgez,pn %g5, longpath ! Invalid, branch out
|
||||
nop ! Delay-slot
|
||||
9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
|
||||
retry ! Trap return
|
||||
nop
|
||||
|
||||
/* DTLB ** ICACHE line 3: winfixups+real_faults */
|
||||
longpath:
|
||||
rdpr %pstate, %g5 ! Move into alternate globals
|
||||
wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate
|
||||
rdpr %tl, %g4 ! See where we came from.
|
||||
cmp %g4, 1 ! Is etrap/rtrap window fault?
|
||||
mov TLB_TAG_ACCESS, %g4 ! Prepare for fault processing
|
||||
ldxa [%g4] ASI_DMMU, %g5 ! Load faulting VA page
|
||||
be,pt %xcc, sparc64_realfault_common ! Jump to normal fault handling
|
||||
mov FAULT_CODE_DTLB, %g4 ! It was read from DTLB
|
||||
|
||||
/* DTLB ** ICACHE line 4: Unused... */
|
||||
ba,a,pt %xcc, winfix_trampoline ! Call window fixup code
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
#undef CREATE_VPTE_OFFSET1
|
||||
#undef CREATE_VPTE_OFFSET2
|
||||
@@ -0,0 +1,39 @@
|
||||
/* DTLB ** ICACHE line 1: Context 0 check and TSB load */
|
||||
ldxa [%g0] ASI_DMMU_TSB_8KB_PTR, %g1 ! Get TSB 8K pointer
|
||||
ldxa [%g0] ASI_DMMU, %g6 ! Get TAG TARGET
|
||||
srlx %g6, 48, %g5 ! Get context
|
||||
sllx %g6, 22, %g6 ! Zero out context
|
||||
brz,pn %g5, kvmap_dtlb ! Context 0 processing
|
||||
srlx %g6, 22, %g6 ! Delay slot
|
||||
TSB_LOAD_QUAD(%g1, %g4) ! Load TSB entry
|
||||
cmp %g4, %g6 ! Compare TAG
|
||||
|
||||
/* DTLB ** ICACHE line 2: TSB compare and TLB load */
|
||||
bne,pn %xcc, tsb_miss_dtlb ! Miss
|
||||
mov FAULT_CODE_DTLB, %g3
|
||||
stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Load TLB
|
||||
retry ! Trap done
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* DTLB ** ICACHE line 3: */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* DTLB ** ICACHE line 4: */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
@@ -277,10 +277,9 @@ static inline void *ebus_alloc(size_t size)
|
||||
{
|
||||
void *mem;
|
||||
|
||||
mem = kmalloc(size, GFP_ATOMIC);
|
||||
mem = kzalloc(size, GFP_ATOMIC);
|
||||
if (!mem)
|
||||
panic("ebus_alloc: out of memory");
|
||||
memset((char *)mem, 0, size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
+232
-99
@@ -50,7 +50,8 @@ do_fpdis:
|
||||
add %g0, %g0, %g0
|
||||
ba,a,pt %xcc, rtrap_clr_l6
|
||||
|
||||
1: ldub [%g6 + TI_FPSAVED], %g5
|
||||
1: TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
ldub [%g6 + TI_FPSAVED], %g5
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
andcc %g5, FPRS_FEF, %g0
|
||||
be,a,pt %icc, 1f
|
||||
@@ -96,10 +97,22 @@ do_fpdis:
|
||||
add %g6, TI_FPREGS + 0x80, %g1
|
||||
faddd %f0, %f2, %f4
|
||||
fmuld %f0, %f2, %f6
|
||||
ldxa [%g3] ASI_DMMU, %g5
|
||||
|
||||
661: ldxa [%g3] ASI_DMMU, %g5
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
ldxa [%g3] ASI_MMU, %g5
|
||||
.previous
|
||||
|
||||
sethi %hi(sparc64_kern_sec_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
|
||||
stxa %g2, [%g3] ASI_DMMU
|
||||
|
||||
661: stxa %g2, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
add %g6, TI_FPREGS + 0xc0, %g2
|
||||
faddd %f0, %f2, %f8
|
||||
@@ -125,11 +138,23 @@ do_fpdis:
|
||||
fzero %f32
|
||||
mov SECONDARY_CONTEXT, %g3
|
||||
fzero %f34
|
||||
ldxa [%g3] ASI_DMMU, %g5
|
||||
|
||||
661: ldxa [%g3] ASI_DMMU, %g5
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
ldxa [%g3] ASI_MMU, %g5
|
||||
.previous
|
||||
|
||||
add %g6, TI_FPREGS, %g1
|
||||
sethi %hi(sparc64_kern_sec_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
|
||||
stxa %g2, [%g3] ASI_DMMU
|
||||
|
||||
661: stxa %g2, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
add %g6, TI_FPREGS + 0x40, %g2
|
||||
faddd %f32, %f34, %f36
|
||||
@@ -154,10 +179,22 @@ do_fpdis:
|
||||
nop
|
||||
3: mov SECONDARY_CONTEXT, %g3
|
||||
add %g6, TI_FPREGS, %g1
|
||||
ldxa [%g3] ASI_DMMU, %g5
|
||||
|
||||
661: ldxa [%g3] ASI_DMMU, %g5
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
ldxa [%g3] ASI_MMU, %g5
|
||||
.previous
|
||||
|
||||
sethi %hi(sparc64_kern_sec_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
|
||||
stxa %g2, [%g3] ASI_DMMU
|
||||
|
||||
661: stxa %g2, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
mov 0x40, %g2
|
||||
membar #Sync
|
||||
@@ -168,7 +205,13 @@ do_fpdis:
|
||||
ldda [%g1 + %g2] ASI_BLK_S, %f48
|
||||
membar #Sync
|
||||
fpdis_exit:
|
||||
stxa %g5, [%g3] ASI_DMMU
|
||||
|
||||
661: stxa %g5, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g5, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
fpdis_exit2:
|
||||
wr %g7, 0, %gsr
|
||||
@@ -189,6 +232,7 @@ fp_other_bounce:
|
||||
.globl do_fpother_check_fitos
|
||||
.align 32
|
||||
do_fpother_check_fitos:
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
sethi %hi(fp_other_bounce - 4), %g7
|
||||
or %g7, %lo(fp_other_bounce - 4), %g7
|
||||
|
||||
@@ -312,6 +356,7 @@ fitos_emul_fini:
|
||||
.globl do_fptrap
|
||||
.align 32
|
||||
do_fptrap:
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
stx %fsr, [%g6 + TI_XFSR]
|
||||
do_fptrap_after_fsr:
|
||||
ldub [%g6 + TI_FPSAVED], %g3
|
||||
@@ -321,10 +366,22 @@ do_fptrap_after_fsr:
|
||||
rd %gsr, %g3
|
||||
stx %g3, [%g6 + TI_GSR]
|
||||
mov SECONDARY_CONTEXT, %g3
|
||||
ldxa [%g3] ASI_DMMU, %g5
|
||||
|
||||
661: ldxa [%g3] ASI_DMMU, %g5
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
ldxa [%g3] ASI_MMU, %g5
|
||||
.previous
|
||||
|
||||
sethi %hi(sparc64_kern_sec_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_sec_context)], %g2
|
||||
stxa %g2, [%g3] ASI_DMMU
|
||||
|
||||
661: stxa %g2, [%g3] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g3] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
add %g6, TI_FPREGS, %g2
|
||||
andcc %g1, FPRS_DL, %g0
|
||||
@@ -339,7 +396,13 @@ do_fptrap_after_fsr:
|
||||
stda %f48, [%g2 + %g3] ASI_BLK_S
|
||||
5: mov SECONDARY_CONTEXT, %g1
|
||||
membar #Sync
|
||||
stxa %g5, [%g1] ASI_DMMU
|
||||
|
||||
661: stxa %g5, [%g1] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g5, [%g1] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
ba,pt %xcc, etrap
|
||||
wr %g0, 0, %fprs
|
||||
@@ -353,8 +416,6 @@ do_fptrap_after_fsr:
|
||||
*
|
||||
* With this method we can do most of the cross-call tlb/cache
|
||||
* flushing very quickly.
|
||||
*
|
||||
* Current CPU's IRQ worklist table is locked into %g6, don't touch.
|
||||
*/
|
||||
.text
|
||||
.align 32
|
||||
@@ -378,6 +439,8 @@ do_ivec:
|
||||
sllx %g2, %g4, %g2
|
||||
sllx %g4, 2, %g4
|
||||
|
||||
TRAP_LOAD_IRQ_WORK(%g6, %g1)
|
||||
|
||||
lduw [%g6 + %g4], %g5 /* g5 = irq_work(cpu, pil) */
|
||||
stw %g5, [%g3 + 0x00] /* bucket->irq_chain = g5 */
|
||||
stw %g3, [%g6 + %g4] /* irq_work(cpu, pil) = bucket */
|
||||
@@ -399,76 +462,6 @@ do_ivec_xcall:
|
||||
1: jmpl %g3, %g0
|
||||
nop
|
||||
|
||||
.globl save_alternate_globals
|
||||
save_alternate_globals: /* %o0 = save_area */
|
||||
rdpr %pstate, %o5
|
||||
andn %o5, PSTATE_IE, %o1
|
||||
wrpr %o1, PSTATE_AG, %pstate
|
||||
stx %g0, [%o0 + 0x00]
|
||||
stx %g1, [%o0 + 0x08]
|
||||
stx %g2, [%o0 + 0x10]
|
||||
stx %g3, [%o0 + 0x18]
|
||||
stx %g4, [%o0 + 0x20]
|
||||
stx %g5, [%o0 + 0x28]
|
||||
stx %g6, [%o0 + 0x30]
|
||||
stx %g7, [%o0 + 0x38]
|
||||
wrpr %o1, PSTATE_IG, %pstate
|
||||
stx %g0, [%o0 + 0x40]
|
||||
stx %g1, [%o0 + 0x48]
|
||||
stx %g2, [%o0 + 0x50]
|
||||
stx %g3, [%o0 + 0x58]
|
||||
stx %g4, [%o0 + 0x60]
|
||||
stx %g5, [%o0 + 0x68]
|
||||
stx %g6, [%o0 + 0x70]
|
||||
stx %g7, [%o0 + 0x78]
|
||||
wrpr %o1, PSTATE_MG, %pstate
|
||||
stx %g0, [%o0 + 0x80]
|
||||
stx %g1, [%o0 + 0x88]
|
||||
stx %g2, [%o0 + 0x90]
|
||||
stx %g3, [%o0 + 0x98]
|
||||
stx %g4, [%o0 + 0xa0]
|
||||
stx %g5, [%o0 + 0xa8]
|
||||
stx %g6, [%o0 + 0xb0]
|
||||
stx %g7, [%o0 + 0xb8]
|
||||
wrpr %o5, 0x0, %pstate
|
||||
retl
|
||||
nop
|
||||
|
||||
.globl restore_alternate_globals
|
||||
restore_alternate_globals: /* %o0 = save_area */
|
||||
rdpr %pstate, %o5
|
||||
andn %o5, PSTATE_IE, %o1
|
||||
wrpr %o1, PSTATE_AG, %pstate
|
||||
ldx [%o0 + 0x00], %g0
|
||||
ldx [%o0 + 0x08], %g1
|
||||
ldx [%o0 + 0x10], %g2
|
||||
ldx [%o0 + 0x18], %g3
|
||||
ldx [%o0 + 0x20], %g4
|
||||
ldx [%o0 + 0x28], %g5
|
||||
ldx [%o0 + 0x30], %g6
|
||||
ldx [%o0 + 0x38], %g7
|
||||
wrpr %o1, PSTATE_IG, %pstate
|
||||
ldx [%o0 + 0x40], %g0
|
||||
ldx [%o0 + 0x48], %g1
|
||||
ldx [%o0 + 0x50], %g2
|
||||
ldx [%o0 + 0x58], %g3
|
||||
ldx [%o0 + 0x60], %g4
|
||||
ldx [%o0 + 0x68], %g5
|
||||
ldx [%o0 + 0x70], %g6
|
||||
ldx [%o0 + 0x78], %g7
|
||||
wrpr %o1, PSTATE_MG, %pstate
|
||||
ldx [%o0 + 0x80], %g0
|
||||
ldx [%o0 + 0x88], %g1
|
||||
ldx [%o0 + 0x90], %g2
|
||||
ldx [%o0 + 0x98], %g3
|
||||
ldx [%o0 + 0xa0], %g4
|
||||
ldx [%o0 + 0xa8], %g5
|
||||
ldx [%o0 + 0xb0], %g6
|
||||
ldx [%o0 + 0xb8], %g7
|
||||
wrpr %o5, 0x0, %pstate
|
||||
retl
|
||||
nop
|
||||
|
||||
.globl getcc, setcc
|
||||
getcc:
|
||||
ldx [%o0 + PT_V9_TSTATE], %o1
|
||||
@@ -488,9 +481,24 @@ setcc:
|
||||
retl
|
||||
stx %o1, [%o0 + PT_V9_TSTATE]
|
||||
|
||||
.globl utrap, utrap_ill
|
||||
utrap: brz,pn %g1, etrap
|
||||
.globl utrap_trap
|
||||
utrap_trap: /* %g3=handler,%g4=level */
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
ldx [%g6 + TI_UTRAPS], %g1
|
||||
brnz,pt %g1, invoke_utrap
|
||||
nop
|
||||
|
||||
ba,pt %xcc, etrap
|
||||
rd %pc, %g7
|
||||
mov %l4, %o1
|
||||
call bad_trap
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
|
||||
invoke_utrap:
|
||||
sllx %g3, 3, %g3
|
||||
ldx [%g1 + %g3], %g1
|
||||
save %sp, -128, %sp
|
||||
rdpr %tstate, %l6
|
||||
rdpr %cwp, %l7
|
||||
@@ -500,17 +508,6 @@ utrap: brz,pn %g1, etrap
|
||||
rdpr %tnpc, %l7
|
||||
wrpr %g1, 0, %tnpc
|
||||
done
|
||||
utrap_ill:
|
||||
call bad_trap
|
||||
add %sp, PTREGS_OFF, %o0
|
||||
ba,pt %xcc, rtrap
|
||||
clr %l6
|
||||
|
||||
/* XXX Here is stuff we still need to write... -DaveM XXX */
|
||||
.globl netbsd_syscall
|
||||
netbsd_syscall:
|
||||
retl
|
||||
nop
|
||||
|
||||
/* We need to carefully read the error status, ACK
|
||||
* the errors, prevent recursive traps, and pass the
|
||||
@@ -1001,7 +998,7 @@ dcpe_icpe_tl1_common:
|
||||
* %g3: scratch
|
||||
* %g4: AFSR
|
||||
* %g5: AFAR
|
||||
* %g6: current thread ptr
|
||||
* %g6: unused, will have current thread ptr after etrap
|
||||
* %g7: scratch
|
||||
*/
|
||||
__cheetah_log_error:
|
||||
@@ -1539,13 +1536,14 @@ ret_from_syscall:
|
||||
|
||||
1: b,pt %xcc, ret_sys_call
|
||||
ldx [%sp + PTREGS_OFF + PT_V9_I0], %o0
|
||||
sparc_exit: wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV), %pstate
|
||||
sparc_exit: rdpr %pstate, %g2
|
||||
wrpr %g2, PSTATE_IE, %pstate
|
||||
rdpr %otherwin, %g1
|
||||
rdpr %cansave, %g3
|
||||
add %g3, %g1, %g3
|
||||
wrpr %g3, 0x0, %cansave
|
||||
wrpr %g0, 0x0, %otherwin
|
||||
wrpr %g0, (PSTATE_RMO | PSTATE_PEF | PSTATE_PRIV | PSTATE_IE), %pstate
|
||||
wrpr %g2, 0x0, %pstate
|
||||
ba,pt %xcc, sys_exit
|
||||
stb %g0, [%g6 + TI_WSAVED]
|
||||
|
||||
@@ -1690,3 +1688,138 @@ __flushw_user:
|
||||
restore %g0, %g0, %g0
|
||||
2: retl
|
||||
nop
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
.globl hard_smp_processor_id
|
||||
hard_smp_processor_id:
|
||||
#endif
|
||||
.globl real_hard_smp_processor_id
|
||||
real_hard_smp_processor_id:
|
||||
__GET_CPUID(%o0)
|
||||
retl
|
||||
nop
|
||||
|
||||
/* %o0: devhandle
|
||||
* %o1: devino
|
||||
*
|
||||
* returns %o0: sysino
|
||||
*/
|
||||
.globl sun4v_devino_to_sysino
|
||||
sun4v_devino_to_sysino:
|
||||
mov HV_FAST_INTR_DEVINO2SYSINO, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
mov %o1, %o0
|
||||
|
||||
/* %o0: sysino
|
||||
*
|
||||
* returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED})
|
||||
*/
|
||||
.globl sun4v_intr_getenabled
|
||||
sun4v_intr_getenabled:
|
||||
mov HV_FAST_INTR_GETENABLED, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
mov %o1, %o0
|
||||
|
||||
/* %o0: sysino
|
||||
* %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED})
|
||||
*/
|
||||
.globl sun4v_intr_setenabled
|
||||
sun4v_intr_setenabled:
|
||||
mov HV_FAST_INTR_SETENABLED, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
|
||||
/* %o0: sysino
|
||||
*
|
||||
* returns %o0: intr_state (HV_INTR_STATE_*)
|
||||
*/
|
||||
.globl sun4v_intr_getstate
|
||||
sun4v_intr_getstate:
|
||||
mov HV_FAST_INTR_GETSTATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
mov %o1, %o0
|
||||
|
||||
/* %o0: sysino
|
||||
* %o1: intr_state (HV_INTR_STATE_*)
|
||||
*/
|
||||
.globl sun4v_intr_setstate
|
||||
sun4v_intr_setstate:
|
||||
mov HV_FAST_INTR_SETSTATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
|
||||
/* %o0: sysino
|
||||
*
|
||||
* returns %o0: cpuid
|
||||
*/
|
||||
.globl sun4v_intr_gettarget
|
||||
sun4v_intr_gettarget:
|
||||
mov HV_FAST_INTR_GETTARGET, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
mov %o1, %o0
|
||||
|
||||
/* %o0: sysino
|
||||
* %o1: cpuid
|
||||
*/
|
||||
.globl sun4v_intr_settarget
|
||||
sun4v_intr_settarget:
|
||||
mov HV_FAST_INTR_SETTARGET, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
|
||||
/* %o0: type
|
||||
* %o1: queue paddr
|
||||
* %o2: num queue entries
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_cpu_qconf
|
||||
sun4v_cpu_qconf:
|
||||
mov HV_FAST_CPU_QCONF, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
|
||||
/* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_cpu_yield
|
||||
sun4v_cpu_yield:
|
||||
mov HV_FAST_CPU_YIELD, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
|
||||
/* %o0: num cpus in cpu list
|
||||
* %o1: cpu list paddr
|
||||
* %o2: mondo block paddr
|
||||
*
|
||||
* returns %o0: status
|
||||
*/
|
||||
.globl sun4v_cpu_mondo_send
|
||||
sun4v_cpu_mondo_send:
|
||||
mov HV_FAST_CPU_MONDO_SEND, %o5
|
||||
ta HV_FAST_TRAP
|
||||
retl
|
||||
nop
|
||||
|
||||
/* %o0: CPU ID
|
||||
*
|
||||
* returns %o0: -status if status non-zero, else
|
||||
* %o0: cpu state as HV_CPU_STATE_*
|
||||
*/
|
||||
.globl sun4v_cpu_state
|
||||
sun4v_cpu_state:
|
||||
mov HV_FAST_CPU_STATE, %o5
|
||||
ta HV_FAST_TRAP
|
||||
brnz,pn %o0, 1f
|
||||
sub %g0, %o0, %o0
|
||||
mov %o1, %o0
|
||||
1: retl
|
||||
nop
|
||||
|
||||
+73
-99
@@ -31,6 +31,7 @@
|
||||
.globl etrap, etrap_irq, etraptl1
|
||||
etrap: rdpr %pil, %g2
|
||||
etrap_irq:
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
rdpr %tstate, %g1
|
||||
sllx %g2, 20, %g3
|
||||
andcc %g1, TSTATE_PRIV, %g0
|
||||
@@ -54,7 +55,31 @@ etrap_irq:
|
||||
rd %y, %g3
|
||||
stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
|
||||
st %g3, [%g2 + STACKFRAME_SZ + PT_V9_Y]
|
||||
save %g2, -STACK_BIAS, %sp ! Ordering here is critical
|
||||
|
||||
rdpr %cansave, %g1
|
||||
brnz,pt %g1, etrap_save
|
||||
nop
|
||||
|
||||
rdpr %cwp, %g1
|
||||
add %g1, 2, %g1
|
||||
wrpr %g1, %cwp
|
||||
be,pt %xcc, etrap_user_spill
|
||||
mov ASI_AIUP, %g3
|
||||
|
||||
rdpr %otherwin, %g3
|
||||
brz %g3, etrap_kernel_spill
|
||||
mov ASI_AIUS, %g3
|
||||
|
||||
etrap_user_spill:
|
||||
|
||||
wr %g3, 0x0, %asi
|
||||
ldx [%g6 + TI_FLAGS], %g3
|
||||
and %g3, _TIF_32BIT, %g3
|
||||
brnz,pt %g3, etrap_user_spill_32bit
|
||||
nop
|
||||
ba,a,pt %xcc, etrap_user_spill_64bit
|
||||
|
||||
etrap_save: save %g2, -STACK_BIAS, %sp
|
||||
mov %g6, %l6
|
||||
|
||||
bne,pn %xcc, 3f
|
||||
@@ -70,42 +95,56 @@ etrap_irq:
|
||||
wrpr %g2, 0, %wstate
|
||||
sethi %hi(sparc64_kern_pri_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3
|
||||
stxa %g3, [%l4] ASI_DMMU
|
||||
flush %l6
|
||||
wr %g0, ASI_AIUS, %asi
|
||||
2: wrpr %g0, 0x0, %tl
|
||||
mov %g4, %l4
|
||||
mov %g5, %l5
|
||||
|
||||
mov %g7, %l2
|
||||
wrpr %g0, ETRAP_PSTATE1, %pstate
|
||||
661: stxa %g3, [%l4] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g3, [%l4] ASI_MMU
|
||||
.previous
|
||||
|
||||
sethi %hi(KERNBASE), %l4
|
||||
flush %l4
|
||||
mov ASI_AIUS, %l7
|
||||
2: mov %g4, %l4
|
||||
mov %g5, %l5
|
||||
add %g7, 4, %l2
|
||||
|
||||
/* Go to trap time globals so we can save them. */
|
||||
661: wrpr %g0, ETRAP_PSTATE1, %pstate
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
SET_GL(0)
|
||||
.previous
|
||||
|
||||
stx %g1, [%sp + PTREGS_OFF + PT_V9_G1]
|
||||
stx %g2, [%sp + PTREGS_OFF + PT_V9_G2]
|
||||
sllx %l7, 24, %l7
|
||||
stx %g3, [%sp + PTREGS_OFF + PT_V9_G3]
|
||||
rdpr %cwp, %l0
|
||||
stx %g4, [%sp + PTREGS_OFF + PT_V9_G4]
|
||||
stx %g5, [%sp + PTREGS_OFF + PT_V9_G5]
|
||||
stx %g6, [%sp + PTREGS_OFF + PT_V9_G6]
|
||||
|
||||
stx %g7, [%sp + PTREGS_OFF + PT_V9_G7]
|
||||
or %l7, %l0, %l7
|
||||
sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0
|
||||
or %l7, %l0, %l7
|
||||
wrpr %l2, %tnpc
|
||||
wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate
|
||||
stx %i0, [%sp + PTREGS_OFF + PT_V9_I0]
|
||||
stx %i1, [%sp + PTREGS_OFF + PT_V9_I1]
|
||||
stx %i2, [%sp + PTREGS_OFF + PT_V9_I2]
|
||||
stx %i3, [%sp + PTREGS_OFF + PT_V9_I3]
|
||||
stx %i4, [%sp + PTREGS_OFF + PT_V9_I4]
|
||||
stx %i5, [%sp + PTREGS_OFF + PT_V9_I5]
|
||||
|
||||
stx %i6, [%sp + PTREGS_OFF + PT_V9_I6]
|
||||
stx %i7, [%sp + PTREGS_OFF + PT_V9_I7]
|
||||
wrpr %g0, ETRAP_PSTATE2, %pstate
|
||||
mov %l6, %g6
|
||||
#ifdef CONFIG_SMP
|
||||
mov TSB_REG, %g3
|
||||
ldxa [%g3] ASI_IMMU, %g5
|
||||
#endif
|
||||
jmpl %l2 + 0x4, %g0
|
||||
ldx [%g6 + TI_TASK], %g4
|
||||
stx %i7, [%sp + PTREGS_OFF + PT_V9_I7]
|
||||
LOAD_PER_CPU_BASE(%g5, %g6, %g4, %g3, %l1)
|
||||
ldx [%g6 + TI_TASK], %g4
|
||||
done
|
||||
|
||||
3: ldub [%l6 + TI_FPDEPTH], %l5
|
||||
3: mov ASI_P, %l7
|
||||
ldub [%l6 + TI_FPDEPTH], %l5
|
||||
add %l6, TI_FPSAVED + 1, %l4
|
||||
srl %l5, 1, %l3
|
||||
add %l5, 2, %l5
|
||||
@@ -125,6 +164,7 @@ etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
|
||||
* 0x58 TL4's TT
|
||||
* 0x60 TL
|
||||
*/
|
||||
TRAP_LOAD_THREAD_REG(%g6, %g1)
|
||||
sub %sp, ((4 * 8) * 4) + 8, %g2
|
||||
rdpr %tl, %g1
|
||||
|
||||
@@ -148,6 +188,11 @@ etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
|
||||
rdpr %tt, %g3
|
||||
stx %g3, [%g2 + STACK_BIAS + 0x38]
|
||||
|
||||
sethi %hi(is_sun4v), %g3
|
||||
lduw [%g3 + %lo(is_sun4v)], %g3
|
||||
brnz,pn %g3, finish_tl1_capture
|
||||
nop
|
||||
|
||||
wrpr %g0, 3, %tl
|
||||
rdpr %tstate, %g3
|
||||
stx %g3, [%g2 + STACK_BIAS + 0x40]
|
||||
@@ -168,91 +213,20 @@ etraptl1: /* Save tstate/tpc/tnpc of TL 1-->4 and the tl register itself.
|
||||
rdpr %tt, %g3
|
||||
stx %g3, [%g2 + STACK_BIAS + 0x78]
|
||||
|
||||
wrpr %g1, %tl
|
||||
stx %g1, [%g2 + STACK_BIAS + 0x80]
|
||||
|
||||
finish_tl1_capture:
|
||||
wrpr %g0, 1, %tl
|
||||
661: nop
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
SET_GL(1)
|
||||
.previous
|
||||
|
||||
rdpr %tstate, %g1
|
||||
sub %g2, STACKFRAME_SZ + TRACEREG_SZ - STACK_BIAS, %g2
|
||||
ba,pt %xcc, 1b
|
||||
andcc %g1, TSTATE_PRIV, %g0
|
||||
|
||||
.align 64
|
||||
.globl scetrap
|
||||
scetrap: rdpr %pil, %g2
|
||||
rdpr %tstate, %g1
|
||||
sllx %g2, 20, %g3
|
||||
andcc %g1, TSTATE_PRIV, %g0
|
||||
or %g1, %g3, %g1
|
||||
bne,pn %xcc, 1f
|
||||
sub %sp, (STACKFRAME_SZ+TRACEREG_SZ-STACK_BIAS), %g2
|
||||
wrpr %g0, 7, %cleanwin
|
||||
|
||||
sllx %g1, 51, %g3
|
||||
sethi %hi(TASK_REGOFF), %g2
|
||||
or %g2, %lo(TASK_REGOFF), %g2
|
||||
brlz,pn %g3, 1f
|
||||
add %g6, %g2, %g2
|
||||
wr %g0, 0, %fprs
|
||||
1: rdpr %tpc, %g3
|
||||
stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TSTATE]
|
||||
|
||||
rdpr %tnpc, %g1
|
||||
stx %g3, [%g2 + STACKFRAME_SZ + PT_V9_TPC]
|
||||
stx %g1, [%g2 + STACKFRAME_SZ + PT_V9_TNPC]
|
||||
save %g2, -STACK_BIAS, %sp ! Ordering here is critical
|
||||
mov %g6, %l6
|
||||
bne,pn %xcc, 2f
|
||||
mov ASI_P, %l7
|
||||
rdpr %canrestore, %g3
|
||||
|
||||
rdpr %wstate, %g2
|
||||
wrpr %g0, 0, %canrestore
|
||||
sll %g2, 3, %g2
|
||||
mov PRIMARY_CONTEXT, %l4
|
||||
wrpr %g3, 0, %otherwin
|
||||
wrpr %g2, 0, %wstate
|
||||
sethi %hi(sparc64_kern_pri_context), %g2
|
||||
ldx [%g2 + %lo(sparc64_kern_pri_context)], %g3
|
||||
stxa %g3, [%l4] ASI_DMMU
|
||||
flush %l6
|
||||
|
||||
mov ASI_AIUS, %l7
|
||||
2: mov %g4, %l4
|
||||
mov %g5, %l5
|
||||
add %g7, 0x4, %l2
|
||||
wrpr %g0, ETRAP_PSTATE1, %pstate
|
||||
stx %g1, [%sp + PTREGS_OFF + PT_V9_G1]
|
||||
stx %g2, [%sp + PTREGS_OFF + PT_V9_G2]
|
||||
sllx %l7, 24, %l7
|
||||
|
||||
stx %g3, [%sp + PTREGS_OFF + PT_V9_G3]
|
||||
rdpr %cwp, %l0
|
||||
stx %g4, [%sp + PTREGS_OFF + PT_V9_G4]
|
||||
stx %g5, [%sp + PTREGS_OFF + PT_V9_G5]
|
||||
stx %g6, [%sp + PTREGS_OFF + PT_V9_G6]
|
||||
stx %g7, [%sp + PTREGS_OFF + PT_V9_G7]
|
||||
or %l7, %l0, %l7
|
||||
sethi %hi(TSTATE_RMO | TSTATE_PEF), %l0
|
||||
|
||||
or %l7, %l0, %l7
|
||||
wrpr %l2, %tnpc
|
||||
wrpr %l7, (TSTATE_PRIV | TSTATE_IE), %tstate
|
||||
stx %i0, [%sp + PTREGS_OFF + PT_V9_I0]
|
||||
stx %i1, [%sp + PTREGS_OFF + PT_V9_I1]
|
||||
stx %i2, [%sp + PTREGS_OFF + PT_V9_I2]
|
||||
stx %i3, [%sp + PTREGS_OFF + PT_V9_I3]
|
||||
stx %i4, [%sp + PTREGS_OFF + PT_V9_I4]
|
||||
|
||||
stx %i5, [%sp + PTREGS_OFF + PT_V9_I5]
|
||||
stx %i6, [%sp + PTREGS_OFF + PT_V9_I6]
|
||||
mov %l6, %g6
|
||||
stx %i7, [%sp + PTREGS_OFF + PT_V9_I7]
|
||||
#ifdef CONFIG_SMP
|
||||
mov TSB_REG, %g3
|
||||
ldxa [%g3] ASI_IMMU, %g5
|
||||
#endif
|
||||
ldx [%g6 + TI_TASK], %g4
|
||||
done
|
||||
|
||||
#undef TASK_REGOFF
|
||||
#undef ETRAP_PSTATE1
|
||||
|
||||
+176
-86
@@ -26,6 +26,7 @@
|
||||
#include <asm/head.h>
|
||||
#include <asm/ttable.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/cpudata.h>
|
||||
|
||||
/* This section from from _start to sparc64_boot_end should fit into
|
||||
* 0x0000000000404000 to 0x0000000000408000.
|
||||
@@ -94,12 +95,17 @@ sparc64_boot:
|
||||
wrpr %g1, 0x0, %pstate
|
||||
ba,a,pt %xcc, 1f
|
||||
|
||||
.globl prom_finddev_name, prom_chosen_path
|
||||
.globl prom_getprop_name, prom_mmu_name
|
||||
.globl prom_callmethod_name, prom_translate_name
|
||||
.globl prom_finddev_name, prom_chosen_path, prom_root_node
|
||||
.globl prom_getprop_name, prom_mmu_name, prom_peer_name
|
||||
.globl prom_callmethod_name, prom_translate_name, prom_root_compatible
|
||||
.globl prom_map_name, prom_unmap_name, prom_mmu_ihandle_cache
|
||||
.globl prom_boot_mapped_pc, prom_boot_mapping_mode
|
||||
.globl prom_boot_mapping_phys_high, prom_boot_mapping_phys_low
|
||||
.globl is_sun4v
|
||||
prom_peer_name:
|
||||
.asciz "peer"
|
||||
prom_compatible_name:
|
||||
.asciz "compatible"
|
||||
prom_finddev_name:
|
||||
.asciz "finddevice"
|
||||
prom_chosen_path:
|
||||
@@ -116,7 +122,13 @@ prom_map_name:
|
||||
.asciz "map"
|
||||
prom_unmap_name:
|
||||
.asciz "unmap"
|
||||
prom_sun4v_name:
|
||||
.asciz "sun4v"
|
||||
.align 4
|
||||
prom_root_compatible:
|
||||
.skip 64
|
||||
prom_root_node:
|
||||
.word 0
|
||||
prom_mmu_ihandle_cache:
|
||||
.word 0
|
||||
prom_boot_mapped_pc:
|
||||
@@ -128,8 +140,54 @@ prom_boot_mapping_phys_high:
|
||||
.xword 0
|
||||
prom_boot_mapping_phys_low:
|
||||
.xword 0
|
||||
is_sun4v:
|
||||
.word 0
|
||||
1:
|
||||
rd %pc, %l0
|
||||
|
||||
mov (1b - prom_peer_name), %l1
|
||||
sub %l0, %l1, %l1
|
||||
mov 0, %l2
|
||||
|
||||
/* prom_root_node = prom_peer(0) */
|
||||
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "peer"
|
||||
mov 1, %l3
|
||||
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 1
|
||||
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
|
||||
stx %l2, [%sp + 2047 + 128 + 0x18] ! arg1, 0
|
||||
stx %g0, [%sp + 2047 + 128 + 0x20] ! ret1
|
||||
call %l7
|
||||
add %sp, (2047 + 128), %o0 ! argument array
|
||||
|
||||
ldx [%sp + 2047 + 128 + 0x20], %l4 ! prom root node
|
||||
mov (1b - prom_root_node), %l1
|
||||
sub %l0, %l1, %l1
|
||||
stw %l4, [%l1]
|
||||
|
||||
mov (1b - prom_getprop_name), %l1
|
||||
mov (1b - prom_compatible_name), %l2
|
||||
mov (1b - prom_root_compatible), %l5
|
||||
sub %l0, %l1, %l1
|
||||
sub %l0, %l2, %l2
|
||||
sub %l0, %l5, %l5
|
||||
|
||||
/* prom_getproperty(prom_root_node, "compatible",
|
||||
* &prom_root_compatible, 64)
|
||||
*/
|
||||
stx %l1, [%sp + 2047 + 128 + 0x00] ! service, "getprop"
|
||||
mov 4, %l3
|
||||
stx %l3, [%sp + 2047 + 128 + 0x08] ! num_args, 4
|
||||
mov 1, %l3
|
||||
stx %l3, [%sp + 2047 + 128 + 0x10] ! num_rets, 1
|
||||
stx %l4, [%sp + 2047 + 128 + 0x18] ! arg1, prom_root_node
|
||||
stx %l2, [%sp + 2047 + 128 + 0x20] ! arg2, "compatible"
|
||||
stx %l5, [%sp + 2047 + 128 + 0x28] ! arg3, &prom_root_compatible
|
||||
mov 64, %l3
|
||||
stx %l3, [%sp + 2047 + 128 + 0x30] ! arg4, size
|
||||
stx %g0, [%sp + 2047 + 128 + 0x38] ! ret1
|
||||
call %l7
|
||||
add %sp, (2047 + 128), %o0 ! argument array
|
||||
|
||||
mov (1b - prom_finddev_name), %l1
|
||||
mov (1b - prom_chosen_path), %l2
|
||||
mov (1b - prom_boot_mapped_pc), %l3
|
||||
@@ -238,6 +296,27 @@ prom_boot_mapping_phys_low:
|
||||
add %sp, (192 + 128), %sp
|
||||
|
||||
sparc64_boot_after_remap:
|
||||
sethi %hi(prom_root_compatible), %g1
|
||||
or %g1, %lo(prom_root_compatible), %g1
|
||||
sethi %hi(prom_sun4v_name), %g7
|
||||
or %g7, %lo(prom_sun4v_name), %g7
|
||||
mov 5, %g3
|
||||
1: ldub [%g7], %g2
|
||||
ldub [%g1], %g4
|
||||
cmp %g2, %g4
|
||||
bne,pn %icc, 2f
|
||||
add %g7, 1, %g7
|
||||
subcc %g3, 1, %g3
|
||||
bne,pt %xcc, 1b
|
||||
add %g1, 1, %g1
|
||||
|
||||
sethi %hi(is_sun4v), %g1
|
||||
or %g1, %lo(is_sun4v), %g1
|
||||
mov 1, %g7
|
||||
stw %g7, [%g1]
|
||||
|
||||
2:
|
||||
BRANCH_IF_SUN4V(g1, jump_to_sun4u_init)
|
||||
BRANCH_IF_CHEETAH_BASE(g1,g7,cheetah_boot)
|
||||
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,cheetah_plus_boot)
|
||||
ba,pt %xcc, spitfire_boot
|
||||
@@ -301,20 +380,58 @@ jump_to_sun4u_init:
|
||||
nop
|
||||
|
||||
sun4u_init:
|
||||
BRANCH_IF_SUN4V(g1, sun4v_init)
|
||||
|
||||
/* Set ctx 0 */
|
||||
mov PRIMARY_CONTEXT, %g7
|
||||
stxa %g0, [%g7] ASI_DMMU
|
||||
mov PRIMARY_CONTEXT, %g7
|
||||
stxa %g0, [%g7] ASI_DMMU
|
||||
membar #Sync
|
||||
|
||||
mov SECONDARY_CONTEXT, %g7
|
||||
stxa %g0, [%g7] ASI_DMMU
|
||||
membar #Sync
|
||||
|
||||
mov SECONDARY_CONTEXT, %g7
|
||||
stxa %g0, [%g7] ASI_DMMU
|
||||
membar #Sync
|
||||
ba,pt %xcc, sun4u_continue
|
||||
nop
|
||||
|
||||
BRANCH_IF_ANY_CHEETAH(g1,g7,cheetah_tlb_fixup)
|
||||
sun4v_init:
|
||||
/* Set ctx 0 */
|
||||
mov PRIMARY_CONTEXT, %g7
|
||||
stxa %g0, [%g7] ASI_MMU
|
||||
membar #Sync
|
||||
|
||||
mov SECONDARY_CONTEXT, %g7
|
||||
stxa %g0, [%g7] ASI_MMU
|
||||
membar #Sync
|
||||
ba,pt %xcc, niagara_tlb_fixup
|
||||
nop
|
||||
|
||||
sun4u_continue:
|
||||
BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup)
|
||||
|
||||
ba,pt %xcc, spitfire_tlb_fixup
|
||||
nop
|
||||
|
||||
niagara_tlb_fixup:
|
||||
mov 3, %g2 /* Set TLB type to hypervisor. */
|
||||
sethi %hi(tlb_type), %g1
|
||||
stw %g2, [%g1 + %lo(tlb_type)]
|
||||
|
||||
/* Patch copy/clear ops. */
|
||||
call niagara_patch_copyops
|
||||
nop
|
||||
call niagara_patch_bzero
|
||||
nop
|
||||
call niagara_patch_pageops
|
||||
nop
|
||||
|
||||
/* Patch TLB/cache ops. */
|
||||
call hypervisor_patch_cachetlbops
|
||||
nop
|
||||
|
||||
ba,pt %xcc, tlb_fixup_done
|
||||
nop
|
||||
|
||||
cheetah_tlb_fixup:
|
||||
mov 2, %g2 /* Set TLB type to cheetah+. */
|
||||
BRANCH_IF_CHEETAH_PLUS_OR_FOLLOWON(g1,g7,1f)
|
||||
@@ -411,85 +528,55 @@ setup_trap_table:
|
||||
wrpr %g0, 15, %pil
|
||||
|
||||
/* Make the firmware call to jump over to the Linux trap table. */
|
||||
call prom_set_trap_table
|
||||
sethi %hi(is_sun4v), %o0
|
||||
lduw [%o0 + %lo(is_sun4v)], %o0
|
||||
brz,pt %o0, 1f
|
||||
nop
|
||||
|
||||
TRAP_LOAD_TRAP_BLOCK(%g2, %g3)
|
||||
add %g2, TRAP_PER_CPU_FAULT_INFO, %g2
|
||||
stxa %g2, [%g0] ASI_SCRATCHPAD
|
||||
|
||||
/* Compute physical address:
|
||||
*
|
||||
* paddr = kern_base + (mmfsa_vaddr - KERNBASE)
|
||||
*/
|
||||
sethi %hi(KERNBASE), %g3
|
||||
sub %g2, %g3, %g2
|
||||
sethi %hi(kern_base), %g3
|
||||
ldx [%g3 + %lo(kern_base)], %g3
|
||||
add %g2, %g3, %o1
|
||||
|
||||
call prom_set_trap_table_sun4v
|
||||
sethi %hi(sparc64_ttable_tl0), %o0
|
||||
|
||||
ba,pt %xcc, 2f
|
||||
nop
|
||||
|
||||
1: call prom_set_trap_table
|
||||
sethi %hi(sparc64_ttable_tl0), %o0
|
||||
|
||||
/* Start using proper page size encodings in ctx register. */
|
||||
sethi %hi(sparc64_kern_pri_context), %g3
|
||||
2: sethi %hi(sparc64_kern_pri_context), %g3
|
||||
ldx [%g3 + %lo(sparc64_kern_pri_context)], %g2
|
||||
mov PRIMARY_CONTEXT, %g1
|
||||
stxa %g2, [%g1] ASI_DMMU
|
||||
|
||||
mov PRIMARY_CONTEXT, %g1
|
||||
|
||||
661: stxa %g2, [%g1] ASI_DMMU
|
||||
.section .sun4v_1insn_patch, "ax"
|
||||
.word 661b
|
||||
stxa %g2, [%g1] ASI_MMU
|
||||
.previous
|
||||
|
||||
membar #Sync
|
||||
|
||||
/* The Linux trap handlers expect various trap global registers
|
||||
* to be setup with some fixed values. So here we set these
|
||||
* up very carefully. These globals are:
|
||||
*
|
||||
* Alternate Globals (PSTATE_AG):
|
||||
*
|
||||
* %g6 --> current_thread_info()
|
||||
*
|
||||
* MMU Globals (PSTATE_MG):
|
||||
*
|
||||
* %g1 --> TLB_SFSR
|
||||
* %g2 --> ((_PAGE_VALID | _PAGE_SZ4MB |
|
||||
* _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
|
||||
* ^ 0xfffff80000000000)
|
||||
* (this %g2 value is used for computing the PAGE_OFFSET kernel
|
||||
* TLB entries quickly, the virtual address of the fault XOR'd
|
||||
* with this %g2 value is the PTE to load into the TLB)
|
||||
* %g3 --> VPTE_BASE_CHEETAH or VPTE_BASE_SPITFIRE
|
||||
*
|
||||
* Interrupt Globals (PSTATE_IG, setup by init_irqwork_curcpu()):
|
||||
*
|
||||
* %g6 --> __irq_work[smp_processor_id()]
|
||||
*/
|
||||
|
||||
rdpr %pstate, %o1
|
||||
mov %g6, %o2
|
||||
wrpr %o1, PSTATE_AG, %pstate
|
||||
mov %o2, %g6
|
||||
|
||||
#define KERN_HIGHBITS ((_PAGE_VALID|_PAGE_SZ4MB)^0xfffff80000000000)
|
||||
#define KERN_LOWBITS (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
|
||||
wrpr %o1, PSTATE_MG, %pstate
|
||||
mov TSB_REG, %g1
|
||||
stxa %g0, [%g1] ASI_DMMU
|
||||
membar #Sync
|
||||
stxa %g0, [%g1] ASI_IMMU
|
||||
membar #Sync
|
||||
mov TLB_SFSR, %g1
|
||||
sethi %uhi(KERN_HIGHBITS), %g2
|
||||
or %g2, %ulo(KERN_HIGHBITS), %g2
|
||||
sllx %g2, 32, %g2
|
||||
or %g2, KERN_LOWBITS, %g2
|
||||
|
||||
BRANCH_IF_ANY_CHEETAH(g3,g7,8f)
|
||||
ba,pt %xcc, 9f
|
||||
nop
|
||||
|
||||
8:
|
||||
sethi %uhi(VPTE_BASE_CHEETAH), %g3
|
||||
or %g3, %ulo(VPTE_BASE_CHEETAH), %g3
|
||||
ba,pt %xcc, 2f
|
||||
sllx %g3, 32, %g3
|
||||
|
||||
9:
|
||||
sethi %uhi(VPTE_BASE_SPITFIRE), %g3
|
||||
or %g3, %ulo(VPTE_BASE_SPITFIRE), %g3
|
||||
sllx %g3, 32, %g3
|
||||
|
||||
2:
|
||||
clr %g7
|
||||
#undef KERN_HIGHBITS
|
||||
#undef KERN_LOWBITS
|
||||
|
||||
/* Kill PROM timer */
|
||||
sethi %hi(0x80000000), %o2
|
||||
sllx %o2, 32, %o2
|
||||
wr %o2, 0, %tick_cmpr
|
||||
|
||||
BRANCH_IF_ANY_CHEETAH(o2,o3,1f)
|
||||
BRANCH_IF_SUN4V(o2, 1f)
|
||||
BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
|
||||
|
||||
ba,pt %xcc, 2f
|
||||
nop
|
||||
@@ -502,7 +589,6 @@ setup_trap_table:
|
||||
|
||||
2:
|
||||
wrpr %g0, %g0, %wstate
|
||||
wrpr %o1, 0x0, %pstate
|
||||
|
||||
call init_irqwork_curcpu
|
||||
nop
|
||||
@@ -517,7 +603,7 @@ setup_trap_table:
|
||||
restore
|
||||
|
||||
.globl setup_tba
|
||||
setup_tba: /* i0 = is_starfire */
|
||||
setup_tba:
|
||||
save %sp, -192, %sp
|
||||
|
||||
/* The boot processor is the only cpu which invokes this
|
||||
@@ -536,31 +622,35 @@ setup_tba: /* i0 = is_starfire */
|
||||
restore
|
||||
sparc64_boot_end:
|
||||
|
||||
#include "systbls.S"
|
||||
#include "ktlb.S"
|
||||
#include "tsb.S"
|
||||
#include "etrap.S"
|
||||
#include "rtrap.S"
|
||||
#include "winfixup.S"
|
||||
#include "entry.S"
|
||||
#include "sun4v_tlb_miss.S"
|
||||
#include "sun4v_ivec.S"
|
||||
|
||||
/*
|
||||
* The following skip makes sure the trap table in ttable.S is aligned
|
||||
* on a 32K boundary as required by the v9 specs for TBA register.
|
||||
*
|
||||
* We align to a 32K boundary, then we have the 32K kernel TSB,
|
||||
* then the 32K aligned trap table.
|
||||
*/
|
||||
1:
|
||||
.skip 0x4000 + _start - 1b
|
||||
|
||||
#ifdef CONFIG_SBUS
|
||||
/* This is just a hack to fool make depend config.h discovering
|
||||
strategy: As the .S files below need config.h, but
|
||||
make depend does not find it for them, we include config.h
|
||||
in head.S */
|
||||
#endif
|
||||
.globl swapper_tsb
|
||||
swapper_tsb:
|
||||
.skip (32 * 1024)
|
||||
|
||||
! 0x0000000000408000
|
||||
|
||||
#include "ttable.S"
|
||||
|
||||
#include "systbls.S"
|
||||
|
||||
.data
|
||||
.align 8
|
||||
.globl prom_tba, tlb_type
|
||||
|
||||
+252
-87
@@ -21,6 +21,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/processor.h>
|
||||
@@ -39,6 +40,7 @@
|
||||
#include <asm/cache.h>
|
||||
#include <asm/cpudata.h>
|
||||
#include <asm/auxio.h>
|
||||
#include <asm/head.h>
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void distribute_irqs(void);
|
||||
@@ -136,12 +138,48 @@ out_unlock:
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern unsigned long real_hard_smp_processor_id(void);
|
||||
|
||||
static unsigned int sun4u_compute_tid(unsigned long imap, unsigned long cpuid)
|
||||
{
|
||||
unsigned int tid;
|
||||
|
||||
if (this_is_starfire) {
|
||||
tid = starfire_translate(imap, cpuid);
|
||||
tid <<= IMAP_TID_SHIFT;
|
||||
tid &= IMAP_TID_UPA;
|
||||
} else {
|
||||
if (tlb_type == cheetah || tlb_type == cheetah_plus) {
|
||||
unsigned long ver;
|
||||
|
||||
__asm__ ("rdpr %%ver, %0" : "=r" (ver));
|
||||
if ((ver >> 32UL) == __JALAPENO_ID ||
|
||||
(ver >> 32UL) == __SERRANO_ID) {
|
||||
tid = cpuid << IMAP_TID_SHIFT;
|
||||
tid &= IMAP_TID_JBUS;
|
||||
} else {
|
||||
unsigned int a = cpuid & 0x1f;
|
||||
unsigned int n = (cpuid >> 5) & 0x1f;
|
||||
|
||||
tid = ((a << IMAP_AID_SHIFT) |
|
||||
(n << IMAP_NID_SHIFT));
|
||||
tid &= (IMAP_AID_SAFARI |
|
||||
IMAP_NID_SAFARI);;
|
||||
}
|
||||
} else {
|
||||
tid = cpuid << IMAP_TID_SHIFT;
|
||||
tid &= IMAP_TID_UPA;
|
||||
}
|
||||
}
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
/* Now these are always passed a true fully specified sun4u INO. */
|
||||
void enable_irq(unsigned int irq)
|
||||
{
|
||||
struct ino_bucket *bucket = __bucket(irq);
|
||||
unsigned long imap;
|
||||
unsigned long tid;
|
||||
unsigned long imap, cpuid;
|
||||
|
||||
imap = bucket->imap;
|
||||
if (imap == 0UL)
|
||||
@@ -149,46 +187,37 @@ void enable_irq(unsigned int irq)
|
||||
|
||||
preempt_disable();
|
||||
|
||||
if (tlb_type == cheetah || tlb_type == cheetah_plus) {
|
||||
unsigned long ver;
|
||||
|
||||
__asm__ ("rdpr %%ver, %0" : "=r" (ver));
|
||||
if ((ver >> 32) == 0x003e0016) {
|
||||
/* We set it to our JBUS ID. */
|
||||
__asm__ __volatile__("ldxa [%%g0] %1, %0"
|
||||
: "=r" (tid)
|
||||
: "i" (ASI_JBUS_CONFIG));
|
||||
tid = ((tid & (0x1fUL<<17)) << 9);
|
||||
tid &= IMAP_TID_JBUS;
|
||||
} else {
|
||||
/* We set it to our Safari AID. */
|
||||
__asm__ __volatile__("ldxa [%%g0] %1, %0"
|
||||
: "=r" (tid)
|
||||
: "i" (ASI_SAFARI_CONFIG));
|
||||
tid = ((tid & (0x3ffUL<<17)) << 9);
|
||||
tid &= IMAP_AID_SAFARI;
|
||||
}
|
||||
} else if (this_is_starfire == 0) {
|
||||
/* We set it to our UPA MID. */
|
||||
__asm__ __volatile__("ldxa [%%g0] %1, %0"
|
||||
: "=r" (tid)
|
||||
: "i" (ASI_UPA_CONFIG));
|
||||
tid = ((tid & UPA_CONFIG_MID) << 9);
|
||||
tid &= IMAP_TID_UPA;
|
||||
} else {
|
||||
tid = (starfire_translate(imap, smp_processor_id()) << 26);
|
||||
tid &= IMAP_TID_UPA;
|
||||
}
|
||||
|
||||
/* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
|
||||
* of this SYSIO's preconfigured IGN in the SYSIO Control
|
||||
* Register, the hardware just mirrors that value here.
|
||||
* However for Graphics and UPA Slave devices the full
|
||||
* IMAP_INR field can be set by the programmer here.
|
||||
*
|
||||
* Things like FFB can now be handled via the new IRQ mechanism.
|
||||
/* This gets the physical processor ID, even on uniprocessor,
|
||||
* so we can always program the interrupt target correctly.
|
||||
*/
|
||||
upa_writel(tid | IMAP_VALID, imap);
|
||||
cpuid = real_hard_smp_processor_id();
|
||||
|
||||
if (tlb_type == hypervisor) {
|
||||
unsigned int ino = __irq_ino(irq);
|
||||
int err;
|
||||
|
||||
err = sun4v_intr_settarget(ino, cpuid);
|
||||
if (err != HV_EOK)
|
||||
printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
|
||||
ino, cpuid, err);
|
||||
err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
|
||||
if (err != HV_EOK)
|
||||
printk("sun4v_intr_setenabled(%x): err(%d)\n",
|
||||
ino, err);
|
||||
} else {
|
||||
unsigned int tid = sun4u_compute_tid(imap, cpuid);
|
||||
|
||||
/* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
|
||||
* of this SYSIO's preconfigured IGN in the SYSIO Control
|
||||
* Register, the hardware just mirrors that value here.
|
||||
* However for Graphics and UPA Slave devices the full
|
||||
* IMAP_INR field can be set by the programmer here.
|
||||
*
|
||||
* Things like FFB can now be handled via the new IRQ
|
||||
* mechanism.
|
||||
*/
|
||||
upa_writel(tid | IMAP_VALID, imap);
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
@@ -201,16 +230,26 @@ void disable_irq(unsigned int irq)
|
||||
|
||||
imap = bucket->imap;
|
||||
if (imap != 0UL) {
|
||||
u32 tmp;
|
||||
if (tlb_type == hypervisor) {
|
||||
unsigned int ino = __irq_ino(irq);
|
||||
int err;
|
||||
|
||||
/* NOTE: We do not want to futz with the IRQ clear registers
|
||||
* and move the state to IDLE, the SCSI code does call
|
||||
* disable_irq() to assure atomicity in the queue cmd
|
||||
* SCSI adapter driver code. Thus we'd lose interrupts.
|
||||
*/
|
||||
tmp = upa_readl(imap);
|
||||
tmp &= ~IMAP_VALID;
|
||||
upa_writel(tmp, imap);
|
||||
err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
|
||||
if (err != HV_EOK)
|
||||
printk("sun4v_intr_setenabled(%x): "
|
||||
"err(%d)\n", ino, err);
|
||||
} else {
|
||||
u32 tmp;
|
||||
|
||||
/* NOTE: We do not want to futz with the IRQ clear registers
|
||||
* and move the state to IDLE, the SCSI code does call
|
||||
* disable_irq() to assure atomicity in the queue cmd
|
||||
* SCSI adapter driver code. Thus we'd lose interrupts.
|
||||
*/
|
||||
tmp = upa_readl(imap);
|
||||
tmp &= ~IMAP_VALID;
|
||||
upa_writel(tmp, imap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,6 +287,8 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long
|
||||
return __irq(&pil0_dummy_bucket);
|
||||
}
|
||||
|
||||
BUG_ON(tlb_type == hypervisor);
|
||||
|
||||
/* RULE: Both must be specified in all other cases. */
|
||||
if (iclr == 0UL || imap == 0UL) {
|
||||
prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
|
||||
@@ -275,12 +316,11 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long
|
||||
goto out;
|
||||
}
|
||||
|
||||
bucket->irq_info = kmalloc(sizeof(struct irq_desc), GFP_ATOMIC);
|
||||
bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC);
|
||||
if (!bucket->irq_info) {
|
||||
prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");
|
||||
prom_halt();
|
||||
}
|
||||
memset(bucket->irq_info, 0, sizeof(struct irq_desc));
|
||||
|
||||
/* Ok, looks good, set it up. Don't touch the irq_chain or
|
||||
* the pending flag.
|
||||
@@ -294,6 +334,37 @@ out:
|
||||
return __irq(bucket);
|
||||
}
|
||||
|
||||
unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags)
|
||||
{
|
||||
struct ino_bucket *bucket;
|
||||
unsigned long sysino;
|
||||
|
||||
sysino = sun4v_devino_to_sysino(devhandle, devino);
|
||||
|
||||
bucket = &ivector_table[sysino];
|
||||
|
||||
/* Catch accidental accesses to these things. IMAP/ICLR handling
|
||||
* is done by hypervisor calls on sun4v platforms, not by direct
|
||||
* register accesses.
|
||||
*
|
||||
* But we need to make them look unique for the disable_irq() logic
|
||||
* in free_irq().
|
||||
*/
|
||||
bucket->imap = ~0UL - sysino;
|
||||
bucket->iclr = ~0UL - sysino;
|
||||
|
||||
bucket->pil = pil;
|
||||
bucket->flags = flags;
|
||||
|
||||
bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC);
|
||||
if (!bucket->irq_info) {
|
||||
prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
return __irq(bucket);
|
||||
}
|
||||
|
||||
static void atomic_bucket_insert(struct ino_bucket *bucket)
|
||||
{
|
||||
unsigned long pstate;
|
||||
@@ -482,7 +553,6 @@ void free_irq(unsigned int irq, void *dev_id)
|
||||
bucket = __bucket(irq);
|
||||
if (bucket != &pil0_dummy_bucket) {
|
||||
struct irq_desc *desc = bucket->irq_info;
|
||||
unsigned long imap = bucket->imap;
|
||||
int ent, i;
|
||||
|
||||
for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) {
|
||||
@@ -495,6 +565,8 @@ void free_irq(unsigned int irq, void *dev_id)
|
||||
}
|
||||
|
||||
if (!desc->action_active_mask) {
|
||||
unsigned long imap = bucket->imap;
|
||||
|
||||
/* This unique interrupt source is now inactive. */
|
||||
bucket->flags &= ~IBF_ACTIVE;
|
||||
|
||||
@@ -592,7 +664,18 @@ static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs)
|
||||
break;
|
||||
}
|
||||
if (bp->pil != 0) {
|
||||
upa_writel(ICLR_IDLE, bp->iclr);
|
||||
if (tlb_type == hypervisor) {
|
||||
unsigned int ino = __irq_ino(bp);
|
||||
int err;
|
||||
|
||||
err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
|
||||
if (err != HV_EOK)
|
||||
printk("sun4v_intr_setstate(%x): "
|
||||
"err(%d)\n", ino, err);
|
||||
} else {
|
||||
upa_writel(ICLR_IDLE, bp->iclr);
|
||||
}
|
||||
|
||||
/* Test and add entropy */
|
||||
if (random & SA_SAMPLE_RANDOM)
|
||||
add_interrupt_randomness(irq);
|
||||
@@ -694,7 +777,7 @@ irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
|
||||
val = readb(auxio_register);
|
||||
val |= AUXIO_AUX1_FTCNT;
|
||||
writeb(val, auxio_register);
|
||||
val &= AUXIO_AUX1_FTCNT;
|
||||
val &= ~AUXIO_AUX1_FTCNT;
|
||||
writeb(val, auxio_register);
|
||||
|
||||
doing_pdma = 0;
|
||||
@@ -727,25 +810,23 @@ EXPORT_SYMBOL(probe_irq_off);
|
||||
static int retarget_one_irq(struct irqaction *p, int goal_cpu)
|
||||
{
|
||||
struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table;
|
||||
unsigned long imap = bucket->imap;
|
||||
unsigned int tid;
|
||||
|
||||
while (!cpu_online(goal_cpu)) {
|
||||
if (++goal_cpu >= NR_CPUS)
|
||||
goal_cpu = 0;
|
||||
}
|
||||
|
||||
if (tlb_type == cheetah || tlb_type == cheetah_plus) {
|
||||
tid = goal_cpu << 26;
|
||||
tid &= IMAP_AID_SAFARI;
|
||||
} else if (this_is_starfire == 0) {
|
||||
tid = goal_cpu << 26;
|
||||
tid &= IMAP_TID_UPA;
|
||||
if (tlb_type == hypervisor) {
|
||||
unsigned int ino = __irq_ino(bucket);
|
||||
|
||||
sun4v_intr_settarget(ino, goal_cpu);
|
||||
sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
|
||||
} else {
|
||||
tid = (starfire_translate(imap, goal_cpu) << 26);
|
||||
tid &= IMAP_TID_UPA;
|
||||
unsigned long imap = bucket->imap;
|
||||
unsigned int tid = sun4u_compute_tid(imap, goal_cpu);
|
||||
|
||||
upa_writel(tid | IMAP_VALID, imap);
|
||||
}
|
||||
upa_writel(tid | IMAP_VALID, imap);
|
||||
|
||||
do {
|
||||
if (++goal_cpu >= NR_CPUS)
|
||||
@@ -848,33 +929,114 @@ static void kill_prom_timer(void)
|
||||
|
||||
void init_irqwork_curcpu(void)
|
||||
{
|
||||
register struct irq_work_struct *workp asm("o2");
|
||||
register unsigned long tmp asm("o3");
|
||||
int cpu = hard_smp_processor_id();
|
||||
|
||||
memset(__irq_work + cpu, 0, sizeof(*workp));
|
||||
memset(__irq_work + cpu, 0, sizeof(struct irq_work_struct));
|
||||
}
|
||||
|
||||
/* Make sure we are called with PSTATE_IE disabled. */
|
||||
__asm__ __volatile__("rdpr %%pstate, %0\n\t"
|
||||
: "=r" (tmp));
|
||||
if (tmp & PSTATE_IE) {
|
||||
prom_printf("BUG: init_irqwork_curcpu() called with "
|
||||
"PSTATE_IE enabled, bailing.\n");
|
||||
__asm__ __volatile__("mov %%i7, %0\n\t"
|
||||
: "=r" (tmp));
|
||||
prom_printf("BUG: Called from %lx\n", tmp);
|
||||
static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type)
|
||||
{
|
||||
unsigned long num_entries = 128;
|
||||
unsigned long status;
|
||||
|
||||
status = sun4v_cpu_qconf(type, paddr, num_entries);
|
||||
if (status != HV_EOK) {
|
||||
prom_printf("SUN4V: sun4v_cpu_qconf(%lu:%lx:%lu) failed, "
|
||||
"err %lu\n", type, paddr, num_entries, status);
|
||||
prom_halt();
|
||||
}
|
||||
}
|
||||
|
||||
static void __cpuinit sun4v_register_mondo_queues(int this_cpu)
|
||||
{
|
||||
struct trap_per_cpu *tb = &trap_block[this_cpu];
|
||||
|
||||
register_one_mondo(tb->cpu_mondo_pa, HV_CPU_QUEUE_CPU_MONDO);
|
||||
register_one_mondo(tb->dev_mondo_pa, HV_CPU_QUEUE_DEVICE_MONDO);
|
||||
register_one_mondo(tb->resum_mondo_pa, HV_CPU_QUEUE_RES_ERROR);
|
||||
register_one_mondo(tb->nonresum_mondo_pa, HV_CPU_QUEUE_NONRES_ERROR);
|
||||
}
|
||||
|
||||
static void __cpuinit alloc_one_mondo(unsigned long *pa_ptr, int use_bootmem)
|
||||
{
|
||||
void *page;
|
||||
|
||||
if (use_bootmem)
|
||||
page = alloc_bootmem_low_pages(PAGE_SIZE);
|
||||
else
|
||||
page = (void *) get_zeroed_page(GFP_ATOMIC);
|
||||
|
||||
if (!page) {
|
||||
prom_printf("SUN4V: Error, cannot allocate mondo queue.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
/* Set interrupt globals. */
|
||||
workp = &__irq_work[cpu];
|
||||
__asm__ __volatile__(
|
||||
"rdpr %%pstate, %0\n\t"
|
||||
"wrpr %0, %1, %%pstate\n\t"
|
||||
"mov %2, %%g6\n\t"
|
||||
"wrpr %0, 0x0, %%pstate\n\t"
|
||||
: "=&r" (tmp)
|
||||
: "i" (PSTATE_IG), "r" (workp));
|
||||
*pa_ptr = __pa(page);
|
||||
}
|
||||
|
||||
static void __cpuinit alloc_one_kbuf(unsigned long *pa_ptr, int use_bootmem)
|
||||
{
|
||||
void *page;
|
||||
|
||||
if (use_bootmem)
|
||||
page = alloc_bootmem_low_pages(PAGE_SIZE);
|
||||
else
|
||||
page = (void *) get_zeroed_page(GFP_ATOMIC);
|
||||
|
||||
if (!page) {
|
||||
prom_printf("SUN4V: Error, cannot allocate kbuf page.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
*pa_ptr = __pa(page);
|
||||
}
|
||||
|
||||
static void __cpuinit init_cpu_send_mondo_info(struct trap_per_cpu *tb, int use_bootmem)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
void *page;
|
||||
|
||||
BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64));
|
||||
|
||||
if (use_bootmem)
|
||||
page = alloc_bootmem_low_pages(PAGE_SIZE);
|
||||
else
|
||||
page = (void *) get_zeroed_page(GFP_ATOMIC);
|
||||
|
||||
if (!page) {
|
||||
prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
||||
tb->cpu_mondo_block_pa = __pa(page);
|
||||
tb->cpu_list_pa = __pa(page + 64);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Allocate and register the mondo and error queues for this cpu. */
|
||||
void __cpuinit sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int load)
|
||||
{
|
||||
struct trap_per_cpu *tb = &trap_block[cpu];
|
||||
|
||||
if (alloc) {
|
||||
alloc_one_mondo(&tb->cpu_mondo_pa, use_bootmem);
|
||||
alloc_one_mondo(&tb->dev_mondo_pa, use_bootmem);
|
||||
alloc_one_mondo(&tb->resum_mondo_pa, use_bootmem);
|
||||
alloc_one_kbuf(&tb->resum_kernel_buf_pa, use_bootmem);
|
||||
alloc_one_mondo(&tb->nonresum_mondo_pa, use_bootmem);
|
||||
alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, use_bootmem);
|
||||
|
||||
init_cpu_send_mondo_info(tb, use_bootmem);
|
||||
}
|
||||
|
||||
if (load) {
|
||||
if (cpu != hard_smp_processor_id()) {
|
||||
prom_printf("SUN4V: init mondo on cpu %d not %d\n",
|
||||
cpu, hard_smp_processor_id());
|
||||
prom_halt();
|
||||
}
|
||||
sun4v_register_mondo_queues(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
/* Only invoked on boot processor. */
|
||||
@@ -884,6 +1046,9 @@ void __init init_IRQ(void)
|
||||
kill_prom_timer();
|
||||
memset(&ivector_table[0], 0, sizeof(ivector_table));
|
||||
|
||||
if (tlb_type == hypervisor)
|
||||
sun4v_init_mondo_queues(1, hard_smp_processor_id(), 1, 1);
|
||||
|
||||
/* We need to clear any IRQ's pending in the soft interrupt
|
||||
* registers, a spurious one could be left around from the
|
||||
* PROM timer which we just disabled.
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/* $Id: itlb_base.S,v 1.12 2002/02/09 19:49:30 davem Exp $
|
||||
* itlb_base.S: Front end to ITLB miss replacement strategy.
|
||||
* This is included directly into the trap table.
|
||||
*
|
||||
* Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
|
||||
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
|
||||
*/
|
||||
|
||||
#if PAGE_SHIFT == 13
|
||||
/*
|
||||
* To compute vpte offset, we need to do ((addr >> 13) << 3),
|
||||
* which can be optimized to (addr >> 10) if bits 10/11/12 can
|
||||
* be guaranteed to be 0 ... mmu_context.h does guarantee this
|
||||
* by only using 10 bits in the hwcontext value.
|
||||
*/
|
||||
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
||||
srax r1, 10, r2
|
||||
#define CREATE_VPTE_OFFSET2(r1, r2) nop
|
||||
#else /* PAGE_SHIFT */
|
||||
#define CREATE_VPTE_OFFSET1(r1, r2) \
|
||||
srax r1, PAGE_SHIFT, r2
|
||||
#define CREATE_VPTE_OFFSET2(r1, r2) \
|
||||
sllx r2, 3, r2
|
||||
#endif /* PAGE_SHIFT */
|
||||
|
||||
|
||||
/* Ways we can get here:
|
||||
*
|
||||
* 1) Nucleus instruction misses from module code.
|
||||
* 2) All user instruction misses.
|
||||
*
|
||||
* All real page faults merge their code paths to the
|
||||
* sparc64_realfault_common label below.
|
||||
*/
|
||||
|
||||
/* ITLB ** ICACHE line 1: Quick user TLB misses */
|
||||
mov TLB_SFSR, %g1
|
||||
ldxa [%g1 + %g1] ASI_IMMU, %g4 ! Get TAG_ACCESS
|
||||
CREATE_VPTE_OFFSET1(%g4, %g6) ! Create VPTE offset
|
||||
CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset
|
||||
ldxa [%g3 + %g6] ASI_P, %g5 ! Load VPTE
|
||||
1: brgez,pn %g5, 3f ! Not valid, branch out
|
||||
sethi %hi(_PAGE_EXEC), %g4 ! Delay-slot
|
||||
andcc %g5, %g4, %g0 ! Executable?
|
||||
|
||||
/* ITLB ** ICACHE line 2: Real faults */
|
||||
be,pn %xcc, 3f ! Nope, branch.
|
||||
nop ! Delay-slot
|
||||
2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB
|
||||
retry ! Trap return
|
||||
3: rdpr %pstate, %g4 ! Move into alt-globals
|
||||
wrpr %g4, PSTATE_AG|PSTATE_MG, %pstate
|
||||
rdpr %tpc, %g5 ! And load faulting VA
|
||||
mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB
|
||||
|
||||
/* ITLB ** ICACHE line 3: Finish faults */
|
||||
sparc64_realfault_common: ! Called by dtlb_miss
|
||||
stb %g4, [%g6 + TI_FAULT_CODE]
|
||||
stx %g5, [%g6 + TI_FAULT_ADDR]
|
||||
ba,pt %xcc, etrap ! Save state
|
||||
1: rd %pc, %g7 ! ...
|
||||
call do_sparc64_fault ! Call fault handler
|
||||
add %sp, PTREGS_OFF, %o0! Compute pt_regs arg
|
||||
ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state
|
||||
nop
|
||||
|
||||
/* ITLB ** ICACHE line 4: Window fixups */
|
||||
winfix_trampoline:
|
||||
rdpr %tpc, %g3 ! Prepare winfixup TNPC
|
||||
or %g3, 0x7c, %g3 ! Compute branch offset
|
||||
wrpr %g3, %tnpc ! Write it into TNPC
|
||||
done ! Do it to it
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
#undef CREATE_VPTE_OFFSET1
|
||||
#undef CREATE_VPTE_OFFSET2
|
||||
@@ -0,0 +1,39 @@
|
||||
/* ITLB ** ICACHE line 1: Context 0 check and TSB load */
|
||||
ldxa [%g0] ASI_IMMU_TSB_8KB_PTR, %g1 ! Get TSB 8K pointer
|
||||
ldxa [%g0] ASI_IMMU, %g6 ! Get TAG TARGET
|
||||
srlx %g6, 48, %g5 ! Get context
|
||||
sllx %g6, 22, %g6 ! Zero out context
|
||||
brz,pn %g5, kvmap_itlb ! Context 0 processing
|
||||
srlx %g6, 22, %g6 ! Delay slot
|
||||
TSB_LOAD_QUAD(%g1, %g4) ! Load TSB entry
|
||||
cmp %g4, %g6 ! Compare TAG
|
||||
|
||||
/* ITLB ** ICACHE line 2: TSB compare and TLB load */
|
||||
bne,pn %xcc, tsb_miss_itlb ! Miss
|
||||
mov FAULT_CODE_ITLB, %g3
|
||||
andcc %g5, _PAGE_EXEC_4U, %g0 ! Executable?
|
||||
be,pn %xcc, tsb_do_fault
|
||||
nop ! Delay slot, fill me
|
||||
stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load TLB
|
||||
retry ! Trap done
|
||||
nop
|
||||
|
||||
/* ITLB ** ICACHE line 3: */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* ITLB ** ICACHE line 4: */
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
+222
-137
@@ -4,191 +4,276 @@
|
||||
* Copyright (C) 1996 Eddie C. Dost (ecd@brainaid.de)
|
||||
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
|
||||
* Copyright (C) 1996,98,99 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
*/
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <asm/head.h>
|
||||
#include <asm/asi.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/tsb.h>
|
||||
|
||||
.text
|
||||
.align 32
|
||||
|
||||
/*
|
||||
* On a second level vpte miss, check whether the original fault is to the OBP
|
||||
* range (note that this is only possible for instruction miss, data misses to
|
||||
* obp range do not use vpte). If so, go back directly to the faulting address.
|
||||
* This is because we want to read the tpc, otherwise we have no way of knowing
|
||||
* the 8k aligned faulting address if we are using >8k kernel pagesize. This
|
||||
* also ensures no vpte range addresses are dropped into tlb while obp is
|
||||
* executing (see inherit_locked_prom_mappings() rant).
|
||||
*/
|
||||
sparc64_vpte_nucleus:
|
||||
/* Note that kvmap below has verified that the address is
|
||||
* in the range MODULES_VADDR --> VMALLOC_END already. So
|
||||
* here we need only check if it is an OBP address or not.
|
||||
kvmap_itlb:
|
||||
/* g6: TAG TARGET */
|
||||
mov TLB_TAG_ACCESS, %g4
|
||||
ldxa [%g4] ASI_IMMU, %g4
|
||||
|
||||
/* sun4v_itlb_miss branches here with the missing virtual
|
||||
* address already loaded into %g4
|
||||
*/
|
||||
kvmap_itlb_4v:
|
||||
|
||||
kvmap_itlb_nonlinear:
|
||||
/* Catch kernel NULL pointer calls. */
|
||||
sethi %hi(PAGE_SIZE), %g5
|
||||
cmp %g4, %g5
|
||||
bleu,pn %xcc, kvmap_dtlb_longpath
|
||||
nop
|
||||
|
||||
KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_itlb_load)
|
||||
|
||||
kvmap_itlb_tsb_miss:
|
||||
sethi %hi(LOW_OBP_ADDRESS), %g5
|
||||
cmp %g4, %g5
|
||||
blu,pn %xcc, kern_vpte
|
||||
blu,pn %xcc, kvmap_itlb_vmalloc_addr
|
||||
mov 0x1, %g5
|
||||
sllx %g5, 32, %g5
|
||||
cmp %g4, %g5
|
||||
blu,pn %xcc, vpte_insn_obp
|
||||
blu,pn %xcc, kvmap_itlb_obp
|
||||
nop
|
||||
|
||||
/* These two instructions are patched by paginig_init(). */
|
||||
kern_vpte:
|
||||
sethi %hi(swapper_pgd_zero), %g5
|
||||
lduw [%g5 + %lo(swapper_pgd_zero)], %g5
|
||||
kvmap_itlb_vmalloc_addr:
|
||||
KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath)
|
||||
|
||||
/* With kernel PGD in %g5, branch back into dtlb_backend. */
|
||||
ba,pt %xcc, sparc64_kpte_continue
|
||||
andn %g1, 0x3, %g1 /* Finish PMD offset adjustment. */
|
||||
KTSB_LOCK_TAG(%g1, %g2, %g7)
|
||||
|
||||
vpte_noent:
|
||||
/* Restore previous TAG_ACCESS, %g5 is zero, and we will
|
||||
* skip over the trap instruction so that the top level
|
||||
* TLB miss handler will thing this %g5 value is just an
|
||||
* invalid PTE, thus branching to full fault processing.
|
||||
/* Load and check PTE. */
|
||||
ldxa [%g5] ASI_PHYS_USE_EC, %g5
|
||||
mov 1, %g7
|
||||
sllx %g7, TSB_TAG_INVALID_BIT, %g7
|
||||
brgez,a,pn %g5, kvmap_itlb_longpath
|
||||
KTSB_STORE(%g1, %g7)
|
||||
|
||||
KTSB_WRITE(%g1, %g5, %g6)
|
||||
|
||||
/* fallthrough to TLB load */
|
||||
|
||||
kvmap_itlb_load:
|
||||
|
||||
661: stxa %g5, [%g0] ASI_ITLB_DATA_IN
|
||||
retry
|
||||
.section .sun4v_2insn_patch, "ax"
|
||||
.word 661b
|
||||
nop
|
||||
nop
|
||||
.previous
|
||||
|
||||
/* For sun4v the ASI_ITLB_DATA_IN store and the retry
|
||||
* instruction get nop'd out and we get here to branch
|
||||
* to the sun4v tlb load code. The registers are setup
|
||||
* as follows:
|
||||
*
|
||||
* %g4: vaddr
|
||||
* %g5: PTE
|
||||
* %g6: TAG
|
||||
*
|
||||
* The sun4v TLB load wants the PTE in %g3 so we fix that
|
||||
* up here.
|
||||
*/
|
||||
mov TLB_SFSR, %g1
|
||||
stxa %g4, [%g1 + %g1] ASI_DMMU
|
||||
done
|
||||
ba,pt %xcc, sun4v_itlb_load
|
||||
mov %g5, %g3
|
||||
|
||||
vpte_insn_obp:
|
||||
/* Behave as if we are at TL0. */
|
||||
wrpr %g0, 1, %tl
|
||||
rdpr %tpc, %g4 /* Find original faulting iaddr */
|
||||
srlx %g4, 13, %g4 /* Throw out context bits */
|
||||
sllx %g4, 13, %g4 /* g4 has vpn + ctx0 now */
|
||||
kvmap_itlb_longpath:
|
||||
|
||||
/* Restore previous TAG_ACCESS. */
|
||||
mov TLB_SFSR, %g1
|
||||
stxa %g4, [%g1 + %g1] ASI_IMMU
|
||||
661: rdpr %pstate, %g5
|
||||
wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate
|
||||
.section .sun4v_2insn_patch, "ax"
|
||||
.word 661b
|
||||
SET_GL(1)
|
||||
nop
|
||||
.previous
|
||||
|
||||
sethi %hi(prom_trans), %g5
|
||||
or %g5, %lo(prom_trans), %g5
|
||||
rdpr %tpc, %g5
|
||||
ba,pt %xcc, sparc64_realfault_common
|
||||
mov FAULT_CODE_ITLB, %g4
|
||||
|
||||
1: ldx [%g5 + 0x00], %g6 ! base
|
||||
brz,a,pn %g6, longpath ! no more entries, fail
|
||||
mov TLB_SFSR, %g1 ! and restore %g1
|
||||
ldx [%g5 + 0x08], %g1 ! len
|
||||
add %g6, %g1, %g1 ! end
|
||||
cmp %g6, %g4
|
||||
bgu,pt %xcc, 2f
|
||||
cmp %g4, %g1
|
||||
bgeu,pt %xcc, 2f
|
||||
ldx [%g5 + 0x10], %g1 ! PTE
|
||||
kvmap_itlb_obp:
|
||||
OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_itlb_longpath)
|
||||
|
||||
/* TLB load, restore %g1, and return from trap. */
|
||||
sub %g4, %g6, %g6
|
||||
add %g1, %g6, %g5
|
||||
mov TLB_SFSR, %g1
|
||||
stxa %g5, [%g0] ASI_ITLB_DATA_IN
|
||||
retry
|
||||
KTSB_LOCK_TAG(%g1, %g2, %g7)
|
||||
|
||||
2: ba,pt %xcc, 1b
|
||||
add %g5, (3 * 8), %g5 ! next entry
|
||||
KTSB_WRITE(%g1, %g5, %g6)
|
||||
|
||||
kvmap_do_obp:
|
||||
sethi %hi(prom_trans), %g5
|
||||
or %g5, %lo(prom_trans), %g5
|
||||
srlx %g4, 13, %g4
|
||||
sllx %g4, 13, %g4
|
||||
|
||||
1: ldx [%g5 + 0x00], %g6 ! base
|
||||
brz,a,pn %g6, longpath ! no more entries, fail
|
||||
mov TLB_SFSR, %g1 ! and restore %g1
|
||||
ldx [%g5 + 0x08], %g1 ! len
|
||||
add %g6, %g1, %g1 ! end
|
||||
cmp %g6, %g4
|
||||
bgu,pt %xcc, 2f
|
||||
cmp %g4, %g1
|
||||
bgeu,pt %xcc, 2f
|
||||
ldx [%g5 + 0x10], %g1 ! PTE
|
||||
|
||||
/* TLB load, restore %g1, and return from trap. */
|
||||
sub %g4, %g6, %g6
|
||||
add %g1, %g6, %g5
|
||||
mov TLB_SFSR, %g1
|
||||
stxa %g5, [%g0] ASI_DTLB_DATA_IN
|
||||
retry
|
||||
|
||||
2: ba,pt %xcc, 1b
|
||||
add %g5, (3 * 8), %g5 ! next entry
|
||||
|
||||
/*
|
||||
* On a first level data miss, check whether this is to the OBP range (note
|
||||
* that such accesses can be made by prom, as well as by kernel using
|
||||
* prom_getproperty on "address"), and if so, do not use vpte access ...
|
||||
* rather, use information saved during inherit_prom_mappings() using 8k
|
||||
* pagesize.
|
||||
*/
|
||||
.align 32
|
||||
kvmap:
|
||||
brgez,pn %g4, kvmap_nonlinear
|
||||
ba,pt %xcc, kvmap_itlb_load
|
||||
nop
|
||||
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
kvmap_dtlb_obp:
|
||||
OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_dtlb_longpath)
|
||||
|
||||
KTSB_LOCK_TAG(%g1, %g2, %g7)
|
||||
|
||||
KTSB_WRITE(%g1, %g5, %g6)
|
||||
|
||||
ba,pt %xcc, kvmap_dtlb_load
|
||||
nop
|
||||
|
||||
.align 32
|
||||
kvmap_dtlb_tsb4m_load:
|
||||
KTSB_LOCK_TAG(%g1, %g2, %g7)
|
||||
KTSB_WRITE(%g1, %g5, %g6)
|
||||
ba,pt %xcc, kvmap_dtlb_load
|
||||
nop
|
||||
|
||||
kvmap_dtlb:
|
||||
/* %g6: TAG TARGET */
|
||||
mov TLB_TAG_ACCESS, %g4
|
||||
ldxa [%g4] ASI_DMMU, %g4
|
||||
|
||||
/* sun4v_dtlb_miss branches here with the missing virtual
|
||||
* address already loaded into %g4
|
||||
*/
|
||||
kvmap_dtlb_4v:
|
||||
brgez,pn %g4, kvmap_dtlb_nonlinear
|
||||
nop
|
||||
|
||||
/* Correct TAG_TARGET is already in %g6, check 4mb TSB. */
|
||||
KERN_TSB4M_LOOKUP_TL1(%g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load)
|
||||
|
||||
/* TSB entry address left in %g1, lookup linear PTE.
|
||||
* Must preserve %g1 and %g6 (TAG).
|
||||
*/
|
||||
kvmap_dtlb_tsb4m_miss:
|
||||
sethi %hi(kpte_linear_bitmap), %g2
|
||||
or %g2, %lo(kpte_linear_bitmap), %g2
|
||||
|
||||
/* Clear the PAGE_OFFSET top virtual bits, then shift
|
||||
* down to get a 256MB physical address index.
|
||||
*/
|
||||
sllx %g4, 21, %g5
|
||||
mov 1, %g7
|
||||
srlx %g5, 21 + 28, %g5
|
||||
|
||||
/* Don't try this at home kids... this depends upon srlx
|
||||
* only taking the low 6 bits of the shift count in %g5.
|
||||
*/
|
||||
sllx %g7, %g5, %g7
|
||||
|
||||
/* Divide by 64 to get the offset into the bitmask. */
|
||||
srlx %g5, 6, %g5
|
||||
sllx %g5, 3, %g5
|
||||
|
||||
/* kern_linear_pte_xor[((mask & bit) ? 1 : 0)] */
|
||||
ldx [%g2 + %g5], %g2
|
||||
andcc %g2, %g7, %g0
|
||||
sethi %hi(kern_linear_pte_xor), %g5
|
||||
or %g5, %lo(kern_linear_pte_xor), %g5
|
||||
bne,a,pt %xcc, 1f
|
||||
add %g5, 8, %g5
|
||||
|
||||
1: ldx [%g5], %g2
|
||||
|
||||
.globl kvmap_linear_patch
|
||||
kvmap_linear_patch:
|
||||
#endif
|
||||
ba,pt %xcc, kvmap_load
|
||||
ba,pt %xcc, kvmap_dtlb_tsb4m_load
|
||||
xor %g2, %g4, %g5
|
||||
|
||||
#ifdef CONFIG_DEBUG_PAGEALLOC
|
||||
sethi %hi(swapper_pg_dir), %g5
|
||||
or %g5, %lo(swapper_pg_dir), %g5
|
||||
sllx %g4, 64 - (PGDIR_SHIFT + PGDIR_BITS), %g6
|
||||
srlx %g6, 64 - PAGE_SHIFT, %g6
|
||||
andn %g6, 0x3, %g6
|
||||
lduw [%g5 + %g6], %g5
|
||||
brz,pn %g5, longpath
|
||||
sllx %g4, 64 - (PMD_SHIFT + PMD_BITS), %g6
|
||||
srlx %g6, 64 - PAGE_SHIFT, %g6
|
||||
sllx %g5, 11, %g5
|
||||
andn %g6, 0x3, %g6
|
||||
lduwa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
|
||||
brz,pn %g5, longpath
|
||||
sllx %g4, 64 - PMD_SHIFT, %g6
|
||||
srlx %g6, 64 - PAGE_SHIFT, %g6
|
||||
sllx %g5, 11, %g5
|
||||
andn %g6, 0x7, %g6
|
||||
ldxa [%g5 + %g6] ASI_PHYS_USE_EC, %g5
|
||||
brz,pn %g5, longpath
|
||||
nop
|
||||
ba,a,pt %xcc, kvmap_load
|
||||
#endif
|
||||
kvmap_dtlb_vmalloc_addr:
|
||||
KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)
|
||||
|
||||
kvmap_nonlinear:
|
||||
KTSB_LOCK_TAG(%g1, %g2, %g7)
|
||||
|
||||
/* Load and check PTE. */
|
||||
ldxa [%g5] ASI_PHYS_USE_EC, %g5
|
||||
mov 1, %g7
|
||||
sllx %g7, TSB_TAG_INVALID_BIT, %g7
|
||||
brgez,a,pn %g5, kvmap_dtlb_longpath
|
||||
KTSB_STORE(%g1, %g7)
|
||||
|
||||
KTSB_WRITE(%g1, %g5, %g6)
|
||||
|
||||
/* fallthrough to TLB load */
|
||||
|
||||
kvmap_dtlb_load:
|
||||
|
||||
661: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
|
||||
retry
|
||||
.section .sun4v_2insn_patch, "ax"
|
||||
.word 661b
|
||||
nop
|
||||
nop
|
||||
.previous
|
||||
|
||||
/* For sun4v the ASI_DTLB_DATA_IN store and the retry
|
||||
* instruction get nop'd out and we get here to branch
|
||||
* to the sun4v tlb load code. The registers are setup
|
||||
* as follows:
|
||||
*
|
||||
* %g4: vaddr
|
||||
* %g5: PTE
|
||||
* %g6: TAG
|
||||
*
|
||||
* The sun4v TLB load wants the PTE in %g3 so we fix that
|
||||
* up here.
|
||||
*/
|
||||
ba,pt %xcc, sun4v_dtlb_load
|
||||
mov %g5, %g3
|
||||
|
||||
kvmap_dtlb_nonlinear:
|
||||
/* Catch kernel NULL pointer derefs. */
|
||||
sethi %hi(PAGE_SIZE), %g5
|
||||
cmp %g4, %g5
|
||||
bleu,pn %xcc, kvmap_dtlb_longpath
|
||||
nop
|
||||
|
||||
KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_dtlb_load)
|
||||
|
||||
kvmap_dtlb_tsbmiss:
|
||||
sethi %hi(MODULES_VADDR), %g5
|
||||
cmp %g4, %g5
|
||||
blu,pn %xcc, longpath
|
||||
blu,pn %xcc, kvmap_dtlb_longpath
|
||||
mov (VMALLOC_END >> 24), %g5
|
||||
sllx %g5, 24, %g5
|
||||
cmp %g4, %g5
|
||||
bgeu,pn %xcc, longpath
|
||||
bgeu,pn %xcc, kvmap_dtlb_longpath
|
||||
nop
|
||||
|
||||
kvmap_check_obp:
|
||||
sethi %hi(LOW_OBP_ADDRESS), %g5
|
||||
cmp %g4, %g5
|
||||
blu,pn %xcc, kvmap_vmalloc_addr
|
||||
blu,pn %xcc, kvmap_dtlb_vmalloc_addr
|
||||
mov 0x1, %g5
|
||||
sllx %g5, 32, %g5
|
||||
cmp %g4, %g5
|
||||
blu,pn %xcc, kvmap_do_obp
|
||||
blu,pn %xcc, kvmap_dtlb_obp
|
||||
nop
|
||||
ba,pt %xcc, kvmap_dtlb_vmalloc_addr
|
||||
nop
|
||||
|
||||
kvmap_vmalloc_addr:
|
||||
/* If we get here, a vmalloc addr was accessed, load kernel VPTE. */
|
||||
ldxa [%g3 + %g6] ASI_N, %g5
|
||||
brgez,pn %g5, longpath
|
||||
nop
|
||||
kvmap_dtlb_longpath:
|
||||
|
||||
kvmap_load:
|
||||
/* PTE is valid, load into TLB and return from trap. */
|
||||
stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB
|
||||
retry
|
||||
661: rdpr %pstate, %g5
|
||||
wrpr %g5, PSTATE_AG | PSTATE_MG, %pstate
|
||||
.section .sun4v_2insn_patch, "ax"
|
||||
.word 661b
|
||||
SET_GL(1)
|
||||
ldxa [%g0] ASI_SCRATCHPAD, %g5
|
||||
.previous
|
||||
|
||||
rdpr %tl, %g3
|
||||
cmp %g3, 1
|
||||
|
||||
661: mov TLB_TAG_ACCESS, %g4
|
||||
ldxa [%g4] ASI_DMMU, %g5
|
||||
.section .sun4v_2insn_patch, "ax"
|
||||
.word 661b
|
||||
ldx [%g5 + HV_FAULT_D_ADDR_OFFSET], %g5
|
||||
nop
|
||||
.previous
|
||||
|
||||
be,pt %xcc, sparc64_realfault_common
|
||||
mov FAULT_CODE_DTLB, %g4
|
||||
ba,pt %xcc, winfix_trampoline
|
||||
nop
|
||||
|
||||
@@ -188,6 +188,7 @@ extern void psycho_init(int, char *);
|
||||
extern void schizo_init(int, char *);
|
||||
extern void schizo_plus_init(int, char *);
|
||||
extern void tomatillo_init(int, char *);
|
||||
extern void sun4v_pci_init(int, char *);
|
||||
|
||||
static struct {
|
||||
char *model_name;
|
||||
@@ -204,6 +205,7 @@ static struct {
|
||||
{ "pci108e,8002", schizo_plus_init },
|
||||
{ "SUNW,tomatillo", tomatillo_init },
|
||||
{ "pci108e,a801", tomatillo_init },
|
||||
{ "SUNW,sun4v-pci", sun4v_pci_init },
|
||||
};
|
||||
#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
|
||||
sizeof(pci_controller_table[0]))
|
||||
@@ -283,6 +285,12 @@ int __init pcic_present(void)
|
||||
return pci_controller_scan(pci_is_controller);
|
||||
}
|
||||
|
||||
struct pci_iommu_ops *pci_iommu_ops;
|
||||
EXPORT_SYMBOL(pci_iommu_ops);
|
||||
|
||||
extern struct pci_iommu_ops pci_sun4u_iommu_ops,
|
||||
pci_sun4v_iommu_ops;
|
||||
|
||||
/* Find each controller in the system, attach and initialize
|
||||
* software state structure for each and link into the
|
||||
* pci_controller_root. Setup the controller enough such
|
||||
@@ -290,6 +298,11 @@ int __init pcic_present(void)
|
||||
*/
|
||||
static void __init pci_controller_probe(void)
|
||||
{
|
||||
if (tlb_type == hypervisor)
|
||||
pci_iommu_ops = &pci_sun4v_iommu_ops;
|
||||
else
|
||||
pci_iommu_ops = &pci_sun4u_iommu_ops;
|
||||
|
||||
printk("PCI: Probing for controllers.\n");
|
||||
|
||||
pci_controller_scan(pci_controller_init);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user