You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在QEMU上通过PSCI启动Cortex-A72第二核心及并行实现咨询

基于PSCI HVC启动Cortex-A72次级核心与并行计算实现指南

一、PSCI HVC方式启动次级核心

PSCI的HVC与SMC调用仅指令不同,参数传递规则完全一致,都是通过x0-x7寄存器传递参数,返回值存于x0。

1. 核心实现步骤

  • 解析DTB确认PSCI方法:从设备树psci节点读取method属性,确认值为hvc。
  • 准备PSCI CPU_ON参数:
    • x0:PSCI_CPU_ON功能ID(PSCI 1.0版本为0xc4000003)
    • x1:目标核心的MPIDR(QEMU中Cortex-A72第二个核心的MPIDR通常为0x1,需保留Aff0-Aff2的正确位)
    • x2:次级核心的物理入口地址(必须对齐到要求的地址边界,比如4KB)
  • 执行HVC调用:用hvc #0指令触发PSCI调用,检查返回值是否为PSCI_SUCCESS(0)。

2. 代码示例

汇编层HVC调用封装

.global psci_hvc_call
psci_hvc_call:
    // x0: PSCI功能ID,x1-x7: 参数
    hvc #0
    ret

C层CPU_ON调用逻辑

#define PSCI_CPU_ON 0xc4000003
#define PSCI_SUCCESS 0

int psci_cpu_on(uint64_t target_mpidr, uint64_t entry_addr) {
    register uint64_t func_id __asm__("x0") = PSCI_CPU_ON;
    register uint64_t mpidr __asm__("x1") = target_mpidr;
    register uint64_t entry __asm__("x2") = entry_addr;

    __asm__ volatile ("bl psci_hvc_call"
                      : "+r"(func_id)
                      : "r"(mpidr), "r"(entry)
                      : "x1", "x2", "x3", "x4", "x5", "x6", "x7", "memory");

    return (int)func_id;
}

次级核心入口函数

// 次级核心栈空间(独立于主核心)
static uint8_t secondary_stack[8192] __attribute__((aligned(16)));
#define secondary_stack_top (secondary_stack + sizeof(secondary_stack))

volatile uint8_t secondary_task_done = 0;

void secondary_core_entry(void) {
    // 初始化核心栈
    __asm__ volatile ("mov sp, %0" : : "r"(secondary_stack_top));

    // 执行分配的任务(比如SHA256计算)
    sha256_compute(input_data, input_len, shared_sha256_result);
    
    // 标记任务完成
    secondary_task_done = 1;

    // 进入低功耗等待或循环
    while (1) {
        __asm__ volatile ("wfe");
    }
}

二、并行任务调度与竞争条件处理

1. 任务分配逻辑

通过共享内存结构体传递任务参数与结果,主核心和次级核心各自执行指定计算:

typedef struct {
    uint32_t crc_result;
    uint8_t sha256_result[32];
    volatile uint8_t crc_done;   // 0=未完成,1=完成
    volatile uint8_t sha256_done;
} shared_task_t;

// 放在共享内存段,确保多核心可访问
shared_task_t __attribute__((section(".shared_memory"))) g_shared_task;
  • 主核心流程:初始化标记为0 → 启动次级核心 → 执行CRC32计算 → 标记crc_done=1 → 等待所有任务完成
  • 次级核心流程:执行SHA256计算 → 标记sha256_done=1 → 进入等待

2. 同步机制实现

轻量级标记同步

用volatile修饰共享变量,结合WFE/SEV指令实现低功耗等待:

// 主核心等待任务完成
while (!g_shared_task.crc_done || !g_shared_task.sha256_done) {
    __asm__ volatile ("wfe");
}

// 次级核心完成任务后触发事件
g_shared_task.sha256_done = 1;
__asm__ volatile ("sev");

自旋锁保护共享资源

访问UART这类独占设备时,用ARM LDXR/STXR指令实现自旋锁:

typedef volatile uint32_t spinlock_t;

void spinlock_acquire(spinlock_t *lock) {
    uint32_t tmp;
    do {
        __asm__ volatile (
            "ldxr %w0, [%1]\n"
            "cbnz %w0, 1f\n"
            "stxr %w0, %w2, [%1]\n"
            "1:"
            : "=&r"(tmp)
            : "r"(lock), "r"(1)
            : "memory");
    } while (tmp != 0);
}

void spinlock_release(spinlock_t *lock) {
    __asm__ volatile ("str %w0, [%1]"
                      : : "r"(0), "r"(lock) : "memory");
}

三、共享UART的访问

双核心可以访问同一个UART,但必须通过自旋锁保证互斥访问,避免输出乱码:

spinlock_t uart_lock = 0;

void uart_puts(const char *str) {
    spinlock_acquire(&uart_lock);
    while (*str) {
        // 写入UART数据寄存器
        UART_DATA_REG = *str++;
        // 等待发送完成
        while (!(UART_STATUS_REG & TX_READY_BIT));
    }
    spinlock_release(&uart_lock);
}

内容的提问来源于stack exchange,提问作者Vladouch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 06:57:11