122f287f4SAndrew Jones // SPDX-License-Identifier: GPL-2.0-only 29c92b28eSAndrew Jones /* 39c92b28eSAndrew Jones * Boot secondary CPUs 49c92b28eSAndrew Jones * 59c92b28eSAndrew Jones * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com> 69c92b28eSAndrew Jones */ 79c92b28eSAndrew Jones #include <libcflat.h> 8*0c39d9eaSAndrew Jones #include <alloc_page.h> 922f287f4SAndrew Jones #include <cpumask.h> 109c92b28eSAndrew Jones #include <asm/csr.h> 11*0c39d9eaSAndrew Jones #include <asm/mmu.h> 129c92b28eSAndrew Jones #include <asm/page.h> 139c92b28eSAndrew Jones #include <asm/processor.h> 149c92b28eSAndrew Jones #include <asm/sbi.h> 159c92b28eSAndrew Jones #include <asm/smp.h> 1622f287f4SAndrew Jones 1722f287f4SAndrew Jones cpumask_t cpu_present_mask; 1822f287f4SAndrew Jones cpumask_t cpu_online_mask; 1922f287f4SAndrew Jones cpumask_t cpu_idle_mask; 209c92b28eSAndrew Jones 219c92b28eSAndrew Jones static cpumask_t cpu_started; 229c92b28eSAndrew Jones 239c92b28eSAndrew Jones secondary_func_t secondary_cinit(struct secondary_data *data) 249c92b28eSAndrew Jones { 259c92b28eSAndrew Jones struct thread_info *info; 269c92b28eSAndrew Jones 27*0c39d9eaSAndrew Jones __mmu_enable(data->satp); 289c92b28eSAndrew Jones thread_info_init(); 299c92b28eSAndrew Jones info = current_thread_info(); 309c92b28eSAndrew Jones set_cpu_online(info->cpu, true); 319c92b28eSAndrew Jones smp_send_event(); 329c92b28eSAndrew Jones 339c92b28eSAndrew Jones return data->func; 349c92b28eSAndrew Jones } 359c92b28eSAndrew Jones 369c92b28eSAndrew Jones static void __smp_boot_secondary(int cpu, secondary_func_t func) 379c92b28eSAndrew Jones { 38*0c39d9eaSAndrew Jones struct secondary_data *sp = alloc_pages(1) + SZ_8K - 16; 399c92b28eSAndrew Jones struct sbiret ret; 409c92b28eSAndrew Jones 419c92b28eSAndrew Jones sp -= sizeof(struct secondary_data); 42*0c39d9eaSAndrew Jones sp->satp = csr_read(CSR_SATP); 439c92b28eSAndrew Jones sp->stvec = csr_read(CSR_STVEC); 449c92b28eSAndrew Jones sp->func = func; 459c92b28eSAndrew Jones 469c92b28eSAndrew Jones ret = sbi_hart_start(cpus[cpu].hartid, (unsigned long)&secondary_entry, __pa(sp)); 479c92b28eSAndrew Jones assert(ret.error == SBI_SUCCESS); 489c92b28eSAndrew Jones } 499c92b28eSAndrew Jones 509c92b28eSAndrew Jones void smp_boot_secondary(int cpu, void (*func)(void)) 519c92b28eSAndrew Jones { 529c92b28eSAndrew Jones int ret = cpumask_test_and_set_cpu(cpu, &cpu_started); 539c92b28eSAndrew Jones 549c92b28eSAndrew Jones assert_msg(!ret, "CPU%d already boot once", cpu); 559c92b28eSAndrew Jones __smp_boot_secondary(cpu, func); 569c92b28eSAndrew Jones 579c92b28eSAndrew Jones while (!cpu_online(cpu)) 589c92b28eSAndrew Jones smp_wait_for_event(); 599c92b28eSAndrew Jones } 609c92b28eSAndrew Jones 619c92b28eSAndrew Jones void smp_boot_secondary_nofail(int cpu, void (*func)(void)) 629c92b28eSAndrew Jones { 639c92b28eSAndrew Jones int ret = cpumask_test_and_set_cpu(cpu, &cpu_started); 649c92b28eSAndrew Jones 659c92b28eSAndrew Jones if (!ret) 669c92b28eSAndrew Jones __smp_boot_secondary(cpu, func); 679c92b28eSAndrew Jones 689c92b28eSAndrew Jones while (!cpu_online(cpu)) 699c92b28eSAndrew Jones smp_wait_for_event(); 709c92b28eSAndrew Jones } 71