Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | /* * SN1 Platform specific SMP Support * * Copyright (C) 2000 Silicon Graphics, Inc. * Copyright (C) 2000 Jack Steiner <steiner@sgi.com> */ #include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/spinlock.h> #include <linux/threads.h> #include <linux/sched.h> #include <linux/smp.h> #include <asm/sn/mmzone_sn1.h> #include <asm/sal.h> #include <asm/system.h> #include <asm/io.h> #include <asm/smp.h> #include <asm/current.h> #include <asm/sn/sn_cpuid.h> /* * The following structure is used to pass params thru smp_call_function * to other cpus for flushing TLB ranges. */ typedef struct { unsigned long start; unsigned long end; unsigned long nbits; } ptc_params_t; /* * The following table/struct is for remembering PTC coherency domains. It * is also used to translate sapicid into cpuids. We dont want to start * cpus unless we know their cache domain. */ #ifdef PTC_NOTYET sn_sapicid_info_t sn_sapicid_info[NR_CPUS]; #endif #ifdef PTC_NOTYET /* * NOTE: This is probably not good enough, but I dont want to try to make * it better until I get some statistics on a running system. * At a minimum, we should only send IPIs to 1 processor in each TLB domain * & have it issue a ptc.g on it's own FSB. Also, serialize per FSB, not * globally. * * More likely, we will have to do some work to reduce the frequency of calls to * this routine. */ static void sn1_ptc_local(void *arg) { ptc_params_t *params = arg; unsigned long start, end, nbits; start = params->start; end = params->end; nbits = params->nbits; do { __asm__ __volatile__ ("ptc.l %0,%1" :: "r"(start), "r"(nbits<<2) : "memory"); start += (1UL << nbits); } while (start < end); } void sn1_ptc_global (unsigned long start, unsigned long end, unsigned long nbits) { ptc_params_t params; params.start = start; params.end = end; params.nbits = nbits; if (smp_call_function(sn1_ptc_local, ¶ms, 1, 0) != 0) panic("Unable to do ptc_global - timed out"); sn1_ptc_local(¶ms); } #endif void sn1_send_IPI(int cpuid, int vector, int delivery_mode, int redirect) { long *p, nasid, slice; static int off[4] = {0x1800080, 0x1800088, 0x1a00080, 0x1a00088}; /* * ZZZ - Replace with standard macros when available. */ nasid = cpuid_to_nasid(cpuid); slice = cpuid_to_slice(cpuid); p = (long*)(0xc0000a0000000000LL | (nasid<<33) | off[slice]); #if defined(ZZZBRINGUP) { static int count=0; if (count++ < 10) printk("ZZ sendIPI 0x%x->0x%x, vec %d, nasid 0x%lx, slice %ld, adr 0x%lx\n", smp_processor_id(), cpuid, vector, nasid, slice, (long)p); } #endif mb(); *p = (delivery_mode << 8) | (vector & 0xff); } #ifdef CONFIG_SMP #ifdef PTC_NOTYET static void __init process_sal_ptc_domain_info(ia64_sal_ptc_domain_info_t *di, int domain) { ia64_sal_ptc_domain_proc_entry_t *pe; int i, sapicid, cpuid; pe = __va(di->proc_list); for (i=0; i<di->proc_count; i++, pe++) { sapicid = id_eid_to_sapicid(pe->id, pe->eid); cpuid = cpu_logical_id(sapicid); sn_sapicid_info[cpuid].domain = domain; sn_sapicid_info[cpuid].sapicid = sapicid; } } static void __init process_sal_desc_ptc(ia64_sal_desc_ptc_t *ptc) { ia64_sal_ptc_domain_info_t *di; int i; di = __va(ptc->domain_info); for (i=0; i<ptc->num_domains; i++, di++) { process_sal_ptc_domain_info(di, i); } } #endif void __init init_sn1_smp_config(void) { if (!ia64_ptc_domain_info) { printk("SMP: Can't find PTC domain info. Forcing UP mode\n"); smp_num_cpus = 1; return; } #ifdef PTC_NOTYET memset (sn_sapicid_info, -1, sizeof(sn_sapicid_info)); process_sal_desc_ptc(ia64_ptc_domain_info); #endif } #else /* CONFIG_SMP */ void __init init_sn1_smp_config(void) { #ifdef PTC_NOTYET sn_sapicid_info[0].sapicid = hard_smp_processor_id(); #endif } #endif /* CONFIG_SMP */ |