aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/smp_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/smp_64.c')
-rw-r--r--arch/sparc/kernel/smp_64.c196
1 files changed, 167 insertions, 29 deletions
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index f7642e5a94db..fa44eaf8d897 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -20,7 +20,8 @@
20#include <linux/cache.h> 20#include <linux/cache.h>
21#include <linux/jiffies.h> 21#include <linux/jiffies.h>
22#include <linux/profile.h> 22#include <linux/profile.h>
23#include <linux/lmb.h> 23#include <linux/bootmem.h>
24#include <linux/vmalloc.h>
24#include <linux/cpu.h> 25#include <linux/cpu.h>
25 26
26#include <asm/head.h> 27#include <asm/head.h>
@@ -47,6 +48,8 @@
47#include <asm/ldc.h> 48#include <asm/ldc.h>
48#include <asm/hypervisor.h> 49#include <asm/hypervisor.h>
49 50
51#include "cpumap.h"
52
50int sparc64_multi_core __read_mostly; 53int sparc64_multi_core __read_mostly;
51 54
52DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE; 55DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
@@ -278,7 +281,7 @@ static unsigned long kimage_addr_to_ra(void *p)
278 return kern_base + (val - KERNBASE); 281 return kern_base + (val - KERNBASE);
279} 282}
280 283
281static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg) 284static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg, void **descrp)
282{ 285{
283 extern unsigned long sparc64_ttable_tl0; 286 extern unsigned long sparc64_ttable_tl0;
284 extern unsigned long kern_locked_tte_data; 287 extern unsigned long kern_locked_tte_data;
@@ -298,12 +301,12 @@ static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread
298 "hvtramp_descr.\n"); 301 "hvtramp_descr.\n");
299 return; 302 return;
300 } 303 }
304 *descrp = hdesc;
301 305
302 hdesc->cpu = cpu; 306 hdesc->cpu = cpu;
303 hdesc->num_mappings = num_kernel_image_mappings; 307 hdesc->num_mappings = num_kernel_image_mappings;
304 308
305 tb = &trap_block[cpu]; 309 tb = &trap_block[cpu];
306 tb->hdesc = hdesc;
307 310
308 hdesc->fault_info_va = (unsigned long) &tb->fault_info; 311 hdesc->fault_info_va = (unsigned long) &tb->fault_info;
309 hdesc->fault_info_pa = kimage_addr_to_ra(&tb->fault_info); 312 hdesc->fault_info_pa = kimage_addr_to_ra(&tb->fault_info);
@@ -341,12 +344,12 @@ static struct thread_info *cpu_new_thread = NULL;
341 344
342static int __cpuinit smp_boot_one_cpu(unsigned int cpu) 345static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
343{ 346{
344 struct trap_per_cpu *tb = &trap_block[cpu];
345 unsigned long entry = 347 unsigned long entry =
346 (unsigned long)(&sparc64_cpu_startup); 348 (unsigned long)(&sparc64_cpu_startup);
347 unsigned long cookie = 349 unsigned long cookie =
348 (unsigned long)(&cpu_new_thread); 350 (unsigned long)(&cpu_new_thread);
349 struct task_struct *p; 351 struct task_struct *p;
352 void *descr = NULL;
350 int timeout, ret; 353 int timeout, ret;
351 354
352 p = fork_idle(cpu); 355 p = fork_idle(cpu);
@@ -359,7 +362,8 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
359#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU) 362#if defined(CONFIG_SUN_LDOMS) && defined(CONFIG_HOTPLUG_CPU)
360 if (ldom_domaining_enabled) 363 if (ldom_domaining_enabled)
361 ldom_startcpu_cpuid(cpu, 364 ldom_startcpu_cpuid(cpu,
362 (unsigned long) cpu_new_thread); 365 (unsigned long) cpu_new_thread,
366 &descr);
363 else 367 else
364#endif 368#endif
365 prom_startcpu_cpuid(cpu, entry, cookie); 369 prom_startcpu_cpuid(cpu, entry, cookie);
@@ -383,10 +387,7 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
383 } 387 }
384 cpu_new_thread = NULL; 388 cpu_new_thread = NULL;
385 389
386 if (tb->hdesc) { 390 kfree(descr);
387 kfree(tb->hdesc);
388 tb->hdesc = NULL;
389 }
390 391
391 return ret; 392 return ret;
392} 393}
@@ -1315,6 +1316,8 @@ int __cpu_disable(void)
1315 cpu_clear(cpu, cpu_online_map); 1316 cpu_clear(cpu, cpu_online_map);
1316 ipi_call_unlock(); 1317 ipi_call_unlock();
1317 1318
1319 cpu_map_rebuild();
1320
1318 return 0; 1321 return 0;
1319} 1322}
1320 1323
@@ -1373,36 +1376,171 @@ void smp_send_stop(void)
1373{ 1376{
1374} 1377}
1375 1378
1376unsigned long __per_cpu_base __read_mostly; 1379/**
1377unsigned long __per_cpu_shift __read_mostly; 1380 * pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu
1381 * @cpu: cpu to allocate for
1382 * @size: size allocation in bytes
1383 * @align: alignment
1384 *
1385 * Allocate @size bytes aligned at @align for cpu @cpu. This wrapper
1386 * does the right thing for NUMA regardless of the current
1387 * configuration.
1388 *
1389 * RETURNS:
1390 * Pointer to the allocated area on success, NULL on failure.
1391 */
1392static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
1393 unsigned long align)
1394{
1395 const unsigned long goal = __pa(MAX_DMA_ADDRESS);
1396#ifdef CONFIG_NEED_MULTIPLE_NODES
1397 int node = cpu_to_node(cpu);
1398 void *ptr;
1399
1400 if (!node_online(node) || !NODE_DATA(node)) {
1401 ptr = __alloc_bootmem(size, align, goal);
1402 pr_info("cpu %d has no node %d or node-local memory\n",
1403 cpu, node);
1404 pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n",
1405 cpu, size, __pa(ptr));
1406 } else {
1407 ptr = __alloc_bootmem_node(NODE_DATA(node),
1408 size, align, goal);
1409 pr_debug("per cpu data for cpu%d %lu bytes on node%d at "
1410 "%016lx\n", cpu, size, node, __pa(ptr));
1411 }
1412 return ptr;
1413#else
1414 return __alloc_bootmem(size, align, goal);
1415#endif
1416}
1378 1417
1379EXPORT_SYMBOL(__per_cpu_base); 1418static size_t pcpur_size __initdata;
1380EXPORT_SYMBOL(__per_cpu_shift); 1419static void **pcpur_ptrs __initdata;
1381 1420
1382void __init real_setup_per_cpu_areas(void) 1421static struct page * __init pcpur_get_page(unsigned int cpu, int pageno)
1383{ 1422{
1384 unsigned long paddr, goal, size, i; 1423 size_t off = (size_t)pageno << PAGE_SHIFT;
1385 char *ptr;
1386 1424
1387 /* Copy section for each CPU (we discard the original) */ 1425 if (off >= pcpur_size)
1388 goal = PERCPU_ENOUGH_ROOM; 1426 return NULL;
1389 1427
1390 __per_cpu_shift = PAGE_SHIFT; 1428 return virt_to_page(pcpur_ptrs[cpu] + off);
1391 for (size = PAGE_SIZE; size < goal; size <<= 1UL) 1429}
1392 __per_cpu_shift++; 1430
1431#define PCPU_CHUNK_SIZE (4UL * 1024UL * 1024UL)
1432
1433static void __init pcpu_map_range(unsigned long start, unsigned long end,
1434 struct page *page)
1435{
1436 unsigned long pfn = page_to_pfn(page);
1437 unsigned long pte_base;
1438
1439 BUG_ON((pfn<<PAGE_SHIFT)&(PCPU_CHUNK_SIZE - 1UL));
1440
1441 pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4U |
1442 _PAGE_CP_4U | _PAGE_CV_4U |
1443 _PAGE_P_4U | _PAGE_W_4U);
1444 if (tlb_type == hypervisor)
1445 pte_base = (_PAGE_VALID | _PAGE_SZ4MB_4V |
1446 _PAGE_CP_4V | _PAGE_CV_4V |
1447 _PAGE_P_4V | _PAGE_W_4V);
1448
1449 while (start < end) {
1450 pgd_t *pgd = pgd_offset_k(start);
1451 unsigned long this_end;
1452 pud_t *pud;
1453 pmd_t *pmd;
1454 pte_t *pte;
1455
1456 pud = pud_offset(pgd, start);
1457 if (pud_none(*pud)) {
1458 pmd_t *new;
1459
1460 new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
1461 pud_populate(&init_mm, pud, new);
1462 }
1463
1464 pmd = pmd_offset(pud, start);
1465 if (!pmd_present(*pmd)) {
1466 pte_t *new;
1467
1468 new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE);
1469 pmd_populate_kernel(&init_mm, pmd, new);
1470 }
1393 1471
1394 paddr = lmb_alloc(size * NR_CPUS, PAGE_SIZE); 1472 pte = pte_offset_kernel(pmd, start);
1395 if (!paddr) { 1473 this_end = (start + PMD_SIZE) & PMD_MASK;
1396 prom_printf("Cannot allocate per-cpu memory.\n"); 1474 if (this_end > end)
1397 prom_halt(); 1475 this_end = end;
1476
1477 while (start < this_end) {
1478 unsigned long paddr = pfn << PAGE_SHIFT;
1479
1480 pte_val(*pte) = (paddr | pte_base);
1481
1482 start += PAGE_SIZE;
1483 pte++;
1484 pfn++;
1485 }
1486 }
1487}
1488
1489void __init setup_per_cpu_areas(void)
1490{
1491 size_t dyn_size, static_size = __per_cpu_end - __per_cpu_start;
1492 static struct vm_struct vm;
1493 unsigned long delta, cpu;
1494 size_t pcpu_unit_size;
1495 size_t ptrs_size;
1496
1497 pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE +
1498 PERCPU_DYNAMIC_RESERVE);
1499 dyn_size = pcpur_size - static_size - PERCPU_MODULE_RESERVE;
1500
1501
1502 ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0]));
1503 pcpur_ptrs = alloc_bootmem(ptrs_size);
1504
1505 for_each_possible_cpu(cpu) {
1506 pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PCPU_CHUNK_SIZE,
1507 PCPU_CHUNK_SIZE);
1508
1509 free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size),
1510 PCPU_CHUNK_SIZE - pcpur_size);
1511
1512 memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size);
1398 } 1513 }
1399 1514
1400 ptr = __va(paddr); 1515 /* allocate address and map */
1401 __per_cpu_base = ptr - __per_cpu_start; 1516 vm.flags = VM_ALLOC;
1517 vm.size = num_possible_cpus() * PCPU_CHUNK_SIZE;
1518 vm_area_register_early(&vm, PCPU_CHUNK_SIZE);
1519
1520 for_each_possible_cpu(cpu) {
1521 unsigned long start = (unsigned long) vm.addr;
1522 unsigned long end;
1523
1524 start += cpu * PCPU_CHUNK_SIZE;
1525 end = start + PCPU_CHUNK_SIZE;
1526 pcpu_map_range(start, end, virt_to_page(pcpur_ptrs[cpu]));
1527 }
1402 1528
1403 for (i = 0; i < NR_CPUS; i++, ptr += size) 1529 pcpu_unit_size = pcpu_setup_first_chunk(pcpur_get_page, static_size,
1404 memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); 1530 PERCPU_MODULE_RESERVE, dyn_size,
1531 PCPU_CHUNK_SIZE, vm.addr, NULL);
1532
1533 free_bootmem(__pa(pcpur_ptrs), ptrs_size);
1534
1535 delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
1536 for_each_possible_cpu(cpu) {
1537 __per_cpu_offset(cpu) = delta + cpu * pcpu_unit_size;
1538 }
1405 1539
1406 /* Setup %g5 for the boot cpu. */ 1540 /* Setup %g5 for the boot cpu. */
1407 __local_per_cpu_offset = __per_cpu_offset(smp_processor_id()); 1541 __local_per_cpu_offset = __per_cpu_offset(smp_processor_id());
1542
1543 of_fill_in_cpu_data();
1544 if (tlb_type == hypervisor)
1545 mdesc_fill_in_cpu_data(cpu_all_mask);
1408} 1546}