当前位置: 首页 > news >正文

QEMU RISCV TCG 详解二 -- RISCV CPU Representation

        在 QEMU 里,如何表征 RISCV CPU 呢?该代码就位于 qemu/target/riscv/cpu-qom.h 中。如下:

// qemu/target/riscv/cpu-qom.h:60
OBJECT_DECLARE_CPU_TYPE(RISCVCPU, RISCVCPUClass, RISCV_CPU)

        经过宏扩展(Macro Preprocess)后,有

# 60 "../target/riscv/cpu-qom.h"
typedef struct ArchCPU RISCVCPU;
typedef struct ArchCPU ArchCPU;
typedef struct RISCVCPUClass RISCVCPUClass;
typedef ArchCPU *ArchCPU_autoptr;
typedef GList *ArchCPU_listautoptr;
typedef GSList *ArchCPU_slistautoptr;
typedef GQueue *ArchCPU_queueautoptr;

        其中类型 ArchCPU 就是 QEMU中,对某一 ISA 的 CPU 的表征(Representation)。那么,对于 RISCV ISA来说,自然就是 类型 RISCVCPU 了。

        另外,基于 QEMU 的 QOM 框架,即基于 C 语言来实现的类似与C++中的面向对象机制(Object Oriented Mechanism),有,类型 RISCVCPU 为 InstanceType,其对应的 ClassType 为 RISCVCPUClass。就像之前,C++还没有自己专用的编译器时,需要先将 C++ 编译成 C 再 编译成二进制码那样。也类似于 Objective-C 中的运行时(runtime)那样。

        即,如果由 C++ 实现为:

// pesudo code of RISCV CPU in C++ as in C with QEMU QOM
class RISCVCPUClass {// data membersRISCVCPU cpu;// with some methodsauto methods();// class data membersstatic class_members;// with some class methodsauto class_methods();
}

        即,类型 RISCVCPU 封装了 RISCVCPUClass 的成员及成员函数,RISCVCPUClass 封装了 类成员及函数。其中,实例类型(InstanceType)中有一成员 ObjectClass *class 指向其 RISCVCPUClass。注意,成员函数(member methods)是存放在 Class 中的,而非实例中的。实例只包含对应的数据成员(data member)。

        对于 RISCVCPU 的 QOM 构建过程,会在后续博文进行详细讲解。这就可以简单地,类似上面 C++ 实现的方式进行理解。

        那么,对于 RISCV 的 ArchCPU 的定义如下:

/** RISCVCPU:* @env: #CPURISCVState** A RISCV CPU.*/
struct ArchCPU {CPUState parent_obj;CPURISCVState env;GDBFeature dyn_csr_feature;GDBFeature dyn_vreg_feature;/* Configuration Settings */RISCVCPUConfig cfg;RISCVSATPModes satp_modes;QEMUTimer *pmu_timer;/* A bitmask of Available programmable counters */uint32_t pmu_avail_ctrs;/* Mapping of events to counters */GHashTable *pmu_event_ctr_map;const GPtrArray *decoders;
};

        其中包含了 CPUState parent_obj 以及 CPURISCVState env。

        1. CPUState parent_obj 包含所有不同架构的CPU的共同信息。类似如下C++实现:

// pesudo code of RISCV CPU in C++ as in C with QEMU QOM
class RISCVCPU: public CPUState {// data membersauto data_members;
}class RISCVCPUClass: public CPUClass {// data membersRISCVCPU cpu;// with some methodsauto methods();// class data membersstatic class_members;// with some class methodsauto class_methods();
}

        2.  CPURISCVState env 包含特定架构特有的状态信息,如各个通用寄存器、状态寄存器等。其中 RISCV ISA 的如下:

typedef struct CPUArchState CPURISCVState;
struct CPUArchState {target_ulong gpr[32];target_ulong gprh[32]; /* 64 top bits of the 128-bit registers *//* vector coprocessor state. */...target_ulong pc;.../* Floating-Point state */.../* RISCVMXL, but uint32_t for vmstate migration */.../* 128-bit helpers upper part return value */....../* RNMI */...
};

        其中,在 CPUState 结构体中的最后一个成员,CPUNegativeOffsetState neg,是以ArchCPU::env 为基准来访问,即:

/*** struct CPUState - common state of one CPU core or thread.* @neg: The architectural register state ("cpu_env") immediately follows* CPUState in ArchCPU and is passed to TCG code. The @neg structure holds* some common TCG CPU variables which are accessed with a negative offset* from cpu_env.*/
struct CPUState {
.../** MUST BE LAST in order to minimize the displacement to CPUArchState.*/char neg_align[-sizeof(CPUNegativeOffsetState) % 16] QEMU_ALIGNED(16);CPUNegativeOffsetState neg;
};
/** RISCVCPU:* @env: #CPURISCVState** A RISCV CPU.*/
struct ArchCPU {CPUState parent_obj;CPURISCVState env;
...
}

        由此,可见 CPUState parent_obj 在地址中是位于 CPURISCVState env 前,其最后成员 CPUNegativeOffsetState neg 就刚好位于 env 前面。这个设计,有助于二进制转译后的加速优化,直接通过 env 指针的加减就可以访问对应的成员。后面遇到这使用情况再详细说明。

        另外,该设计也有如下使用方式:

static inline CPUArchState *cpu_env(CPUState *cpu)
{/* We validate that CPUArchState follows CPUState in cpu-target.c */return (CPUArchState *)(cpu + 1);
}/*** env_archcpu(env)* @env: The architecture environment** Return the ArchCPU associated with the environment.*/
static inline ArchCPU *env_archcpu(CPUArchState *env)
{return (void *)env - sizeof(CPUState);
}

        另外,还有就是对应的 RISCVCPUClass,如下:

/*** RISCVCPUClass:* @parent_realize: The parent class' realize handler.* @parent_phases: The parent class' reset phase handlers.** A RISCV CPU model.*/
struct RISCVCPUClass {CPUClass parent_class;DeviceRealize parent_realize;ResettablePhases parent_phases;RISCVCPUDef *def;
};
/*** CPUClass:
...* Represents a CPU family or model.*/
struct CPUClass {
...
/* when TCG is not available, this pointer is NULL */const TCGCPUOps *tcg_ops;
...
};

        其中 tcg_ops 就是 TCG 对特定架构CPU的操作函数,其主要成员如下:

const TCGCPUOps riscv_tcg_ops = {.mttcg_supported = true,.guest_default_memory_order = 0,.initialize = riscv_translate_init,.translate_code = riscv_translate_code,.get_tb_cpu_state = riscv_get_tb_cpu_state,.synchronize_from_tb = riscv_cpu_synchronize_from_tb,.restore_state_to_opc = riscv_restore_state_to_opc,.mmu_index = riscv_cpu_mmu_index,#ifndef CONFIG_USER_ONLY.tlb_fill = riscv_cpu_tlb_fill,.pointer_wrap = riscv_pointer_wrap,.cpu_exec_interrupt = riscv_cpu_exec_interrupt,.cpu_exec_halt = riscv_cpu_has_work,.cpu_exec_reset = cpu_reset,.do_interrupt = riscv_cpu_do_interrupt,.do_transaction_failed = riscv_cpu_do_transaction_failed,.do_unaligned_access = riscv_cpu_do_unaligned_access,.debug_excp_handler = riscv_cpu_debug_excp_handler,.debug_check_breakpoint = riscv_cpu_debug_check_breakpoint,.debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
#endif /* !CONFIG_USER_ONLY */
};

        在 CPUClass 初始化时定义,如下:

/*{.name = TYPE_RISCV_CPU,.parent = TYPE_CPU,.instance_size = sizeof(RISCVCPU),.instance_align = __alignof(RISCVCPU),// 实例初始化函数,类似 instance constructor..instance_init = riscv_cpu_init,.abstract = true,.class_size = sizeof(RISCVCPUClass),// 类初始化函数,类似 class constructor..class_init = riscv_cpu_common_class_init,.class_base_init = riscv_cpu_class_base_init,
}*/static void riscv_cpu_common_class_init(ObjectClass *c, const void *data)
{RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);CPUClass *cc = CPU_CLASS(c);DeviceClass *dc = DEVICE_CLASS(c);ResettableClass *rc = RESETTABLE_CLASS(c);device_class_set_parent_realize(dc, riscv_cpu_realize,&mcc->parent_realize);resettable_class_set_parent_phases(rc, NULL, riscv_cpu_reset_hold, NULL,&mcc->parent_phases);cc->class_by_name = riscv_cpu_class_by_name;cc->dump_state = riscv_cpu_dump_state;cc->set_pc = riscv_cpu_set_pc;cc->get_pc = riscv_cpu_get_pc;cc->gdb_read_register = riscv_cpu_gdb_read_register;cc->gdb_write_register = riscv_cpu_gdb_write_register;cc->gdb_stop_before_watchpoint = true;cc->disas_set_info = riscv_cpu_disas_set_info;
#ifndef CONFIG_USER_ONLYcc->sysemu_ops = &riscv_sysemu_ops;cc->get_arch_id = riscv_get_arch_id;
#endifcc->gdb_arch_name = riscv_gdb_arch_name;
#ifdef CONFIG_TCGcc->tcg_ops = &riscv_tcg_ops;
#endif /* CONFIG_TCG */device_class_set_props(dc, riscv_cpu_properties);
}

        至此,对于 RISCV CPU 在 QEMU 是如何表征有了大致上的了解。后续文章,就会可以继续推进 二进制转译的研究了。敬请期待。

http://www.dtcms.com/a/294416.html

相关文章:

  • 多模态Embedding技术
  • 基于springboot的乡村旅游在线服务系统/乡村旅游网站
  • 汽车网络升级攻略:CAN-CAN FD-车载以太网
  • Qt(基本组件和基本窗口类)
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(8):自動詞 & 他動詞 「~ている」「~ておく」「~てある」
  • 疯狂星期四文案网第16天运营日记
  • vmware分配了ubuntu空间但是ubuntu没有获取
  • Python爬虫--Xpath的应用
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘jupyter’问题
  • 系统架构师:软件工程-思维导图
  • 二十二、【Linux系统防火墙管理】firewalld命令详解
  • 使用yolov10模型检测视频中出现的行人,并保存为图片
  • 电子设计大赛【C语言核心知识点】讲解
  • HF86611_VC1/HF86611Q_VC1:多通道USB HiFi音频解码器固件技术解析
  • 动态路由协议基础
  • MIT6.824 Raft算法Lab2A实验
  • 基于阿里云平台的文章评价模型训练与应用全流程指南
  • CASAIM自动蓝光检测供应商三维测量系统近线检测汽车变速箱尺寸
  • Java SE:类与对象的认识
  • 【kubernetes】-3 pod基础和yaml文件
  • 记录一本设计模式的书
  • vue3与ue5通信-工具类
  • [C/C++内存安全]_[中级]_[安全处理字符串]
  • ctfshow pwn40
  • 保护板测试仪:守护电池安全的“幕后卫士”
  • 关于SPring基础和Vue的学习
  • Docker 容器中的 HEAD 请求缺失 header?从 Content-MD5 缺失聊起
  • 超声原始数据重构成B扫成像的MATLAB实现
  • 【AI News | 20250722】每日AI进展
  • now能减少mysql的压力吗