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> 80c39d9eaSAndrew Jones #include <alloc_page.h> 922f287f4SAndrew Jones #include <cpumask.h> 109c92b28eSAndrew Jones #include <asm/csr.h> 11*92f91f64SAndrew Jones #include <asm/io.h> 120c39d9eaSAndrew Jones #include <asm/mmu.h> 139c92b28eSAndrew Jones #include <asm/page.h> 149c92b28eSAndrew Jones #include <asm/processor.h> 159c92b28eSAndrew Jones #include <asm/sbi.h> 169c92b28eSAndrew Jones #include <asm/smp.h> 1722f287f4SAndrew Jones 1822f287f4SAndrew Jones cpumask_t cpu_present_mask; 1922f287f4SAndrew Jones cpumask_t cpu_online_mask; 2022f287f4SAndrew Jones cpumask_t cpu_idle_mask; 219c92b28eSAndrew Jones 229c92b28eSAndrew Jones static cpumask_t cpu_started; 239c92b28eSAndrew Jones 249c92b28eSAndrew Jones secondary_func_t secondary_cinit(struct secondary_data *data) 259c92b28eSAndrew Jones { 269c92b28eSAndrew Jones struct thread_info *info; 279c92b28eSAndrew Jones 280c39d9eaSAndrew Jones __mmu_enable(data->satp); 299c92b28eSAndrew Jones thread_info_init(); 309c92b28eSAndrew Jones info = current_thread_info(); 319c92b28eSAndrew Jones set_cpu_online(info->cpu, true); 329c92b28eSAndrew Jones smp_send_event(); 339c92b28eSAndrew Jones 349c92b28eSAndrew Jones return data->func; 359c92b28eSAndrew Jones } 369c92b28eSAndrew Jones 379c92b28eSAndrew Jones static void __smp_boot_secondary(int cpu, secondary_func_t func) 389c92b28eSAndrew Jones { 390c39d9eaSAndrew Jones struct secondary_data *sp = alloc_pages(1) + SZ_8K - 16; 40*92f91f64SAndrew Jones phys_addr_t sp_phys; 419c92b28eSAndrew Jones struct sbiret ret; 429c92b28eSAndrew Jones 439c92b28eSAndrew Jones sp -= sizeof(struct secondary_data); 440c39d9eaSAndrew Jones sp->satp = csr_read(CSR_SATP); 459c92b28eSAndrew Jones sp->stvec = csr_read(CSR_STVEC); 469c92b28eSAndrew Jones sp->func = func; 479c92b28eSAndrew Jones 48*92f91f64SAndrew Jones sp_phys = virt_to_phys(sp); 49*92f91f64SAndrew Jones assert(sp_phys == __pa(sp_phys)); 50*92f91f64SAndrew Jones 51*92f91f64SAndrew Jones ret = sbi_hart_start(cpus[cpu].hartid, (unsigned long)&secondary_entry, __pa(sp_phys)); 529c92b28eSAndrew Jones assert(ret.error == SBI_SUCCESS); 539c92b28eSAndrew Jones } 549c92b28eSAndrew Jones 559c92b28eSAndrew Jones void smp_boot_secondary(int cpu, void (*func)(void)) 569c92b28eSAndrew Jones { 579c92b28eSAndrew Jones int ret = cpumask_test_and_set_cpu(cpu, &cpu_started); 589c92b28eSAndrew Jones 599c92b28eSAndrew Jones assert_msg(!ret, "CPU%d already boot once", cpu); 609c92b28eSAndrew Jones __smp_boot_secondary(cpu, func); 619c92b28eSAndrew Jones 629c92b28eSAndrew Jones while (!cpu_online(cpu)) 639c92b28eSAndrew Jones smp_wait_for_event(); 649c92b28eSAndrew Jones } 659c92b28eSAndrew Jones 669c92b28eSAndrew Jones void smp_boot_secondary_nofail(int cpu, void (*func)(void)) 679c92b28eSAndrew Jones { 689c92b28eSAndrew Jones int ret = cpumask_test_and_set_cpu(cpu, &cpu_started); 699c92b28eSAndrew Jones 709c92b28eSAndrew Jones if (!ret) 719c92b28eSAndrew Jones __smp_boot_secondary(cpu, func); 729c92b28eSAndrew Jones 739c92b28eSAndrew Jones while (!cpu_online(cpu)) 749c92b28eSAndrew Jones smp_wait_for_event(); 759c92b28eSAndrew Jones } 76