SMMU存在多个转换阶段,最终输出的内存属性如何决定?

Memory type and shareability attribute determination

在SMMU地址转换过程中,一个transaction从输入到输出,可能会经过多个处理流程。OA(Output Address)最终得到的内存属性shareability属性可能是由多个源(SCR0,CBn_SCTLR,以及page table descriptor等等)的配置组合生成的。

0 Memory type 和 shareability 之间的联系

memory attribute和shareability之间有一定的联系,比如在SMMUv2架构下,如果最终的memory attribute是以下类型,那么其shareability将会被视为 Outer Shareable

  • Strongly-ordered
  • Device
  • Normal Inner Non-cacheable
  • Normal Outer Non-cacheable

所以在一般情况下,一个transaction的最终内存属性,除了translation table,还取决于一些寄存器的字段。下图针对每种事务类型,说明了每个寄存器字段是否适用:
在这里插入图片描述

1, 关键字段详细解析

  1. NSCFG(Non-secure Configuration)
    含义:非安全配置字段,用于设置transaction的安全属性(安全 / 非安全)。
    适用场景:
    • Stage 1 转换表:适用(Y),影响安全状态下的地址转换。
    • SMMU_S2CRn(bypass mode / translation context):适用(Y),可覆盖transaction的安全属性。
    • Stage 1 SMMU_CBn_SCTLR:适用(Y),控制stage 1 context的安全配置。
  2. WACFG(Write-Allocate Configuration)
    含义:写分配配置,控制写操作时是否分配缓存。
    适用场景:
    • Stage 2 转换表:适用(Y),影响stage 2 转换的写分配策略。
    • SMMU_S2CRn(bypass mode / translation context):适用(Y),可覆盖写分配属性。
    • Stage 1/2 SMMU_CBn_SCTLR:适用(Y),控制context的写分配行为。
    • SMMU_CBARn:适用(Y),影响stage 1 + stage 2 bypass mode的写分配。
  3. RACFG(Read-Allocate Configuration)
    含义:读分配配置,控制读操作时是否分配缓存。
    适用场景:与 WACFG 类似,主要在 Stage 2 转换表、SMMU_S2CRn、Stage 1/2 SCTLR 等场景中适用(Y)。
  4. MemAttr(Memory Attribute)
    含义:内存属性,定义内存类型(如stronly ordered、device、normal cacaheable等)。
    适用场景:
    • Stage 1 转换表:通过 SMMU_CBn_MAIRm 选择内存属性。
    • Stage 2 转换表:适用(Y),直接来自translation table descriptor。
    • SMMU_S2CRn(bypass mode / translation context):适用(Y),可覆盖内存属性。
    • Stage 1/2 SCTLR:适用(Y),控制context的内存属性转换。
  5. MTCFG(Memory Type Configuration)
    含义:内存类型配置,决定是否使用 MemAttr 字段覆盖默认属性。
    适用场景:
    • Stage 1 转换表:不适用(N),转换表直接使用 MAIRm。
    • SMMU_S2CRn(bypass mode / translation context):适用(Y),启用 MemAttr 覆盖。
  6. SHCFG(Shareability Configuration)
    含义:共享性配置,定义内存的共享范围(non-shareable、inner-shareable、outer-shareable)。
    适用场景:在转换表、SMMU_S2CRn、SCTLR、CBARn 中均适用(Y),影响事务的缓存一致性。
  7. INSTCFG(Instruction Configuration)
    含义:指令配置,区分事务是指令访问还是数据访问。
    适用场景:
    • Stage 1 转换表:部分确定权限故障(如指令执行权限检查)。
    • SMMU_S2CRn(转换上下文):适用(Y),可覆盖指令 / 数据属性。
  8. PRIVCFG(Privilege Configuration)
    含义:权限配置,区分事务的特权级别(特权 / 非特权)。
    适用场景:
    • Stage 2 转换表:部分确定权限故障(如特权访问检查)。
    • SMMU_S2CRn(转换上下文):适用(Y),可覆盖权限属性。

2, 关键符号与注释说明

transaction的最终属性由转换表内容和多个寄存器字段共同决定,不同阶段(Stage 1/2)和context(tranlastion mode/ bypass mode)的寄存器会覆盖或补充转换表的属性,从而影响内存访问的安全状态、缓存策略、权限检查等关键行为。例如:

  • SMMU_S2CRn在bypass mode下可完全覆盖属性;
  • 转换表通过 MAIRm 等寄存器定义基础属性;
  • SCTLR和CBARn控制context级别的属性转换逻辑。

下表展示了当上游总线系统不支持特定总线标记时,SMMU 必须如何处理上游总线标记

AttributeTreated as
NSCFGNon-secure
RACFGAllocate
WACFGAllocate
MemAttrWrite-Back, Write-Allocate
SHCFGNon-shared
INSTCFGData
PRIVCFGUnprivileged
TRANSIENTCFGNon-transient

当下游总线系统不支持特定的总线标记时,SMMU 实现可能不会为该属性提供存储。除了 NSCFG(非安全配置)和 PRIVCFG(特权配置)外,表中的相应字段可能会被置为 RAZ/WI(读任意值 / 写无效)。
以下是详细解释:

  1. 下游总线标记不支持的场景
    下游总线(如连接内存或外设的总线)可能无法支持某些属性标记(如安全状态、缓存策略等)。此时,SMMU 作为中间组件,需处理上游总线传入的标记,但下游总线无法识别这些标记。
  2. SMMU 的处理逻辑
    属性存储省略:若下游总线不支持某属性(如共享性、内存类型),SMMU 可能不会为该属性保留存储单元,即硬件不实现相关寄存器或字段。
    RAZ/WI 行为:除 NSCFG 和 PRIVCFG 外,其他字段会被设为 RAZ/WI:
    • RAZ(Read Any Value):读取时返回任意值(硬件未定义)。
    • WI(Write Ignore):写入时被忽略,不影响实际功能。
  3. NSCFG 和 PRIVCFG 的例外
    NSCFG(非安全配置):无论下游总线是否支持,该字段必须保留,因为它涉及安全状态的核心控制(安全 / 非安全事务区分),是系统安全隔离的基础。
    PRIVCFG(特权配置):用于区分特权 / 非特权访问,影响内存权限检查,是权限管理的关键属性,必须保留存储。
  4. 示例场景
    案例 1:下游总线不支持共享性标记(SHCFG)
    SMMU 的 SHCFG 字段设为 RAZ/WI,即上游事务的共享性属性(如 “外部共享”)无法传递到下游,下游总线按默认非共享处理。
    案例 2:下游总线不支持瞬态标记(TRANSIENTCFG)
    TRANSIENTCFG 字段被忽略,SMMU 不会将上游的瞬态属性传递给下游,数据按非瞬态处理。
  5. 设计意图
  • 兼容性:允许 SMMU 适配不同下游总线,避免因下游限制导致系统功能失效。
  • 安全与权限优先:NSCFG 和 PRIVCFG 的保留确保安全状态和权限控制的基本功能不受下游限制影响,维持系统安全性和稳定性。

简而言之,除安全状态和权限相关字段外,下游不支持的标记会被 SMMU 忽略,以适配硬件限制,同时保证核心安全和权限机制的有效性。

一,SMMU_sCR0 的控制-Bypassing the Stream mapping table

如果任何SMMU_sCR0设置导致transaction bypass Stream mapping table,则SMMU_sCR0会为该transaction指定内存属性转换。

1、transaction 绕过流映射表的三大触发条件

当以下任意条件满足时,transaction 将绕过流映射表(Stream Mapping Table):

1. SMMU_sCR0.CLIENTPD = 1

  • 含义:Client Port Disable标志位生效,此时transaction 无需经过流映射表,直接进入bypass mode。

2. transaction 不匹配流映射表项且SMMU_sCR0.USFCFG = 0

  • USFCFG(Unsupported Stream Fault Configuration)
    • 当USFCFG=0时,若transaction 无法匹配流映射表中的任何条目,直接绕过映射表,不触发错误;
    • 若USFCFG=1,则会触发未支持流错误(Unsupported Stream Fault)。

3. transaction 匹配多个流映射表项且SMMU_sCR0.SMCFCFG = 0

  • SMCFCFG(Stream Match Conflict Fault Configuration):
    • 当SMCFCFG=0时,若事务匹配多个表项(映射冲突),直接绕过映射表;
    • 若SMCFCFG=1,则触发匹配冲突错误。

2、绕过流映射表后的transaction 处理流程

  1. 地址转换与属性处理

    • 地址转换禁用:transaction 不进行stage1和2的地址转换,直接使用原始地址。
    • 仅属性转换:通过SMMU_sCR0的对应副本进行属性转换(如内存类型、共享性等),但不改变地址。
  2. 保护检查的例外情况

    • 数据访问:完全跳过保护检查(如权限、安全状态检查)。
    • 指令获取
      • 若实现支持双安全状态(Secure/Non-secure),可能触发权限检查;
      • 非安全指令获取通常跳过检查,安全指令获取可能根据配置进行检查。

3、双安全状态(Secure/Non-secure)下的特殊处理规则

  • 非安全事务:由SMMU_CR0.CLIENTPD控制(仅对非安全事务有效);
  • 安全事务:由SMMU_SCR0.CLIENTPD控制(安全状态下的等效字段)。

安全指令获取的权限检查

  • SMMU_SCR1.SIF位(Secure Instruction Fetch)
    • 当SIF=1时,若安全事务(SSD)经SMMU转换后生成非安全指令总线标记,会记录权限故障;
    • 故障记录位置:
      • 全局故障:记录到SMMU_SGFSR;
      • 关联特定context bank:记录到SMMU_CBn_FSR。

关键寄存器与标志位总结

寄存器/位作用
SMMU_CR0.CLIENTPD控制非安全事务的bypass,置1时 bypass 流映射表。
SMMU_SCR0.CLIENTPD安全事务的 CLIENTPD 控制位,功能与非安全状态等效。
SMMU_sCR0.USFCFG控制未匹配流映射表时的行为:0= bypass,1=触发错误。
SMMU_sCR0.SMCFCFG控制映射冲突时的行为:0= bypass,1=触发错误。
SMMU_SCR1.SIF安全指令获取的权限检查开关,置1时检查安全事务的指令总线标记合法性。

总结流程图示
请添加图片描述
需要注意的是,一个non-secure的client 发出的instruction fetch,并不受任何安全检查

保护检查的触发条件

当以下条件同时满足时,安全指令获取事务会触发保护检查:

  • SMMU_SCR1.SIF 位设为 1
    SIF(Secure Instruction Fetch)位启用安全指令获取的权限检查功能。
  • 事务类型为 SSD Secure Transaction
    SSD(Secure State Device)事务属于安全世界,目标是访问安全内存。
  • SMMU 生成非安全指令总线标记的下游事务
    尽管输入是安全事务,但 SMMU 处理后生成的下游事务被标记为非安全(Non-secure)的指令访问,这属于安全状态转换错误。

绕过流映射表的机制在保证系统性能和兼容性的同时,通过选择性保护检查维持安全边界,是SMMU在处理异常事务时的关键容错机制。

二, SMMU_S2CRn + SMMU_CBn_SCTLR

上文考虑的是SMMU_sCR0设为bypass SMT的情况,如果stream 匹配成功,有且只匹配到一个stream mapping table entry,并且通过这个entry 找到了 contex bank,这种情况下,我们继续往下讨论。
同样地,如果SMMU_S2CRn.TYPE字段指定初始上下文为bypass mode,即绕过address translation,则SMMU_S2CRn会为该transaction 指定内存属性转换。
对于使用stage 1转换context bank的转换,SMMU_S2CRn会指定第一个内存属性转换,然后根据以下规则处理:

1、SMMU_CBn_SCTLR.M位的两种状态及属性处理逻辑

1.1 当SMMU_CBn_SCTLR.M = 0(禁用context bank的MMU行为)
  • 核心行为:仅进行属性转换,不执行地址转换(即不查询转换表)。
  • 属性处理流程
    1. SMMU_S2CRn 先对事务的内存属性进行首次转换(如覆盖内存类型、共享性等)。
    2. SMMU_CBn_SCTLR 负责后续的属性转换,即根据该寄存器的配置进一步修改属性。
  • 示例场景
    • SMMU_S2CRn将内存类型设为「device memory」,SMMU_CBn_SCTLR进一步将共享性设为「非共享」,最终属性为「device memory+非共享」。
1.2 当SMMU_CBn_SCTLR.M = 1(启用context bank的MMU行为)
  • 核心行为:启用地址转换,需查询转换表(Translation Table)获取属性。
  • 属性处理流程
    1. SMMU_S2CRn 完成首次属性转换后,
    2. 转换表描述符 会指定最终属性,并覆盖SMMU_S2CRn的大部分配置(除权限相关属性外)。
  • 示例场景
    • SMMU_S2CRn将内存类型设为「normal memory」,但转换表描述符指定「写回缓存+外部共享」,最终属性以转换表为准。

三、Stage 1描述符对属性的覆盖规则

当转换表(Stage1描述符)指定属性时,会覆盖SMMU_S2CRn的大部分字段,仅保留以下权限相关属性:

1. INSTCFG(指令配置)
  • 作用:区分transaction是「指令访问」还是「数据访问」,影响权限检查(如指令执行权限)。
  • 示例:若转换表允许数据访问但禁止指令执行,INSTCFG设为「数据」时transaction可正常访问,设为「指令」时触发权限故障。
2. PRIVCFG(特权配置)
  • 作用:指定事务的特权级别(「特权」或「非特权」),与内存的访问权限(如AP位)共同决定是否允许访问。
  • 示例:PRIVCFG设为「非特权」时,transaction只能访问非特权内存区域,否则触发权限故障。
3. 权限字段保留的原因分析

主要是考虑到权限检查,验证transaction是否有权限访问目标内存(如特权级别、指令执行权限等),INSTCFG和PRIVCFG直接影响事务的权限合法性,若被转换表覆盖可能导致安全漏洞(如非特权事务访问特权内存)。因此,这两个字段必须由SMMU_S2CRn显式控制,确保权限检查的准确性。

四,阶段1与阶段2内存属性的组合逻辑解析

1、SMMU_CBARn.TYPE字段对属性组合的影响

SMMU的阶段1和阶段2属性组合规则取决于SMMU_CBARn.TYPE字段指定的context bank格式,具体分为以下两种场景:

1.Stage1 + Stage2 bypass(TYPE=0b01)

  • 核心逻辑:Stage1 转换完成后,不执行Stage2地址转换,直接由Stage1 的SMMU_CBARn寄存器指定Stage2的内存属性。
  • 属性处理流程
    1. Stage2转换生成IPA(中间物理地址),并由SMMU_S2CRn和Stage1 转换表完成首次属性转换。
    2. 阶段2属性由Stage1的SMMU_CBARn直接指定,无需查询Stage2转换表。例如:
      • SMMU_CBARn将Stage2属性设为「写回缓存+外部共享」,则最终属性为阶段1属性与该配置的组合。

所以所谓的stage2 bypass,指的是address translation bypass,stage2的memory attribute 仍可以通过CBAR进行生效。

2. .Stage1 + Stage2(TYPE=0b00)

  • 核心逻辑:Stage1转换后执行Stage2转换,阶段2属性由SMMU_CBn_SCTLR.M位控制获取方式。
  • 属性处理流程
    • 当SMMU_CBn_SCTLR.M=0(禁用Stage2 MMU行为)
      Stage2属性由Stage2的SMMU_CBn_SCTLR寄存器指定,不查询Stage2转换表。例如:
      • Stage1属性为「device memory」,Stage2的SMMU_CBn_SCTLR设为「非共享」,最终属性为「device memory+非共享」。
    • 当SMMU_CBn_SCTLR.M=1(启用Stage2 MMU行为)
      Stage2属性由Stage2转换表描述符指定,覆盖Stage2寄存器的配置(除权限相关属性外)。例如:
      • Stage2寄存器设为「写通缓存」,但转换表描述符指定「写回缓存」,最终属性以转换表为准。

2、当SMMU_S2CRn指定初始context为translation contex时的属性处理逻辑

1、关键前提条件

  1. SMMU_S2CRn指定初始context为translation context
    • 意味着transaction进入正常的地址转换流程,而非Bypass模式,需经过阶段1和阶段2转换。
  2. SMMU_CBARn指定阶段2 translation context
    • 明确阶段2转换的context bank,即阶段1转换完成后,阶段2转换将使用该bank的配置。
      请添加图片描述

2、阶段1属性的处理流程

  1. SMMU_S2CRn对阶段1属性的首次转换
    • SMMU_S2CRn会先对阶段1的输入属性进行转换,例如:
      • 覆盖内存类型(MemAttr)、共享性(SHCFG)、分配策略(RACFG/WACFG)等。
  2. 转换后的阶段1属性作为阶段2的输入
    • 阶段1转换后的属性(已由SMMU_S2CRn处理)将作为阶段2转换的原始输入属性,而非直接使用上游总线的属性。

3、典型应用场景

  1. 虚拟化环境中的内存隔离
    • 阶段1由Guest OS控制,阶段2由Hypervisor控制,通过SMMU_S2CRn和阶段2转换表实现Guest内存到物理内存的映射及属性隔离。
  2. 设备直通(Device Passthrough)
    • 阶段1转换映射设备虚拟地址到IPA,阶段2转换直接由寄存器指定属性,避免复杂的转换表查询,提升性能。

五、Stage 1与Stage 2内存属性的组合规则及内存属性强弱规则

1、ARM架构下属性组合的核心原则

Stage 1和Stage 2的内存属性需按ARM架构规范组合,其中Stage 2属性只能强化内存类型(即Stage 2属性的内存类型强度不能低于Stage 1)。内存类型按强度从高到低排序如下:

2、通用内存类型强弱排序(适用于ARMv7/ARMv8)

内存类型强度等级特性描述
Strongly-ordered(强有序)最高访问严格按程序顺序执行,禁止乱序和推测访问,常用于设备寄存器等对时序敏感的场景。
Device(设备内存)次高支持设备访问,禁止缓存,部分类型允许写提前确认(Early Write Acknowledgement)。
Non-cacheable to normal中等正常内存的非缓存模式,数据直接访问内存,不经过缓存。
Write-through to normal中低正常内存的写通模式,写操作同时更新缓存和内存,保证数据一致性。
Write-Back to normal最低正常内存的写回模式,写操作先更新缓存,仅在缓存行替换时写入内存,性能最优但一致性稍弱。

3、ARMv8特有的Device内存类型细分(按强度排序)

ARMv8 Device类型强度等级与ARMv7的对应关系关键特性
Device-nGnRnE最高等效于ARMv7的Strongly-ordered非聚合、非重排序、无写提前确认,访问严格有序,禁止任何推测和乱序。
Device-nGnRE次高等效于ARMv7的Device非聚合、非重排序、有写提前确认,允许写操作提前确认但禁止数据重排序。
Device-nGRE中高ARMv8新增类型非聚合、可重排序、有写提前确认,需通过内存屏障(Barrier)保证访问顺序,允许有限重排序。
Device-GRE最低ARMv8新增类型聚合、可重排序、有写提前确认,限制最少(类似Normal内存),但禁止推测访问设备内存。

4、Stage 2属性强化内存类型的示例

  • 场景1:Stage 1属性为Write-Back normal(最低强度)

    • Stage 2属性可强化为Write-through normal、Non-cacheable normal、Device或Strongly-ordered。
    • 禁止操作:Stage 2不能将属性降级为比Write-Back更弱的类型(无更弱类型)。
  • 场景2:Stage 1属性为Device-nGnRE(次高强度)

    • Stage 2属性可强化为Device-nGnRnE或Strongly-ordered。
    • 禁止操作:Stage 2不能将属性降级为Device-nGRE、Device-GRE或Normal内存类型。

5、共享性(Shareability)强度排序

共享性属性按影响范围从大到小(强度从高到低)排序:

  1. Outer Shareable(外部共享)
    • 多个处理器或集群之间共享,需保证跨外部缓存层次的一致性(如不同CPU集群间的缓存同步)。
  2. Inner Shareable(内部共享)
    • 同一处理器内部共享,仅需保证内部缓存层次的一致性(如同一CPU内的多个核心间同步)。
  3. Non-shareable(非共享)
    • 不共享,不同处理器或设备的缓存无需同步,适用于设备内存等场景。

6、属性组合的架构设计目的

  1. 安全性与兼容性
    • Stage 2属性只能强化内存类型,避免因属性降级导致的缓存一致性漏洞(如将设备内存误判为可缓存内存,导致数据不一致)。
  2. 性能优化
    • 通过细粒度的Device类型(如ARMv8的Device-GRE),在保证设备访问约束的前提下,允许更灵活的内存操作,提升系统性能。
  3. 跨架构兼容性
    • ARMv8的Device类型与ARMv7保持功能等效(如Device-nGnRE对应ARMv7的Device),确保软件在不同架构间的兼容性。

7、典型应用场景

  • 虚拟化环境
    Stage 1由Guest OS配置为Normal内存(Write-Back),Stage 2由Hypervisor强化为Device内存,确保设备访问的严格时序。
  • 设备驱动开发
    对时序敏感的设备寄存器访问,通过Stage 2将内存类型强化为Strongly-ordered,避免因乱序访问导致设备异常。

8、关键规则总结

  1. 内存类型组合公式
    最终属性 = max(Stage 1属性强度, Stage 2属性强度),其中Stage 2属性不能低于Stage 1。
  2. 共享性组合逻辑
    最终共享性取Stage 1和Stage 2中强度更高的属性(如Stage 1为Inner Shareable,Stage 2为Outer Shareable,则最终为Outer Shareable)。
  3. ARMv8 Device类型扩展
    通过细分Device类型,在保证设备访问约束的同时,允许更精细的性能优化(如Device-GRE支持有限重排序,提升设备访问效率)。

六,Reserved Attributes的处理

1、Reserved Attributes的定义与背景

在ARM架构的SMMU(System Memory Management Unit)中,部分内存类型(Memory Type)和共享属性(Shareability Attributes)的编码被标记为Reserved(保留)。这些保留值在硬件设计中未被正式定义功能,若软件错误使用可能导致不可预测的行为。不同SMMU版本(如SMMUv1和SMMUv2)对保留值的处理规则存在显著差异,以下结合规范详细说明。

2、SMMUv1与SMMUv2对Reserved值的处理差异

  1. SMMUv1的不确定性

    • 若软件将属性设置为Reserved值,其行为是不可预测(UNPREDICTABLE),可能导致系统异常或功能错误。
    • 例如:内存类型或共享属性的保留值可能被硬件误解析,进而影响内存访问的顺序性、缓存策略或安全状态。
  2. SMMUv2的标准化处理

    • SMMUv2对部分保留值定义了明确的“替代语义”,即硬件会将保留值自动映射为特定的有效属性,以避免不可预测的行为。
    • 软件读取保留值时,硬件会返回原始设置的保留值(即保留值具有“可读可写”特性,但实际功能按映射后的属性生效)。

3、SMMUv2中Reserved属性的具体映射规则

属性Reserved值SMMUv2映射后的含义
NSCFG0b01映射为0b11,表示非安全(Non-secure)状态
WACFG0b01映射为0b00,使用默认写分配属性
RACFG0b01映射为0b00,使用默认读分配属性
MemAttr[3:0]0b0100, 0b1000, 0b1100映射为0b0000,表示强有序(Strongly-ordered)或设备(Device)内存类型
BPSHCFG0b00映射为0b01,表示外部可共享(Outer Shareable)
INSTCFG0b01映射为0b11,表示指令访问
PRIVCFG0b01(当SMMU_IDR2.DIPANS=0时)映射为0b10,表示非特权(unprivileged)访问
TRANSIENTCFG0b01映射为0b00,使用默认瞬态属性

关键说明:

  • MemAttr[3:0]:保留值(如0b0100)会被映射为强有序或设备内存类型,这类内存具有严格的访问顺序约束,禁止缓存或乱序操作。
  • NSCFG:保留值0b01强制映射为非安全状态,确保安全属性的一致性。
  • BPSHCFG:保留值0b00映射为外部可共享,影响多核系统中缓存一致性的范围(Outer Shareable表示跨cluster共享)。

4、Reserved Attributes与内存类型和共享属性的关联

Reserved属性的处理规则与内存类型、共享属性的核心特性紧密相关:

  • 内存类型(如Strongly-ordered、Device)决定了内存访问的顺序性和缓存策略,保留值的映射确保了关键属性的正确性。
  • 共享属性(如Outer Shareable)影响缓存一致性域的范围,保留值的映射避免了多核系统中的数据不一致风险。

通过标准化保留值的处理,SMMUv2在兼容性和可靠性之间取得了平衡,而SMMUv1的不确定性则要求软件必须严格规避保留值的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值