qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

cxl_component.h (8868B)


      1 /*
      2  * QEMU CXL Component
      3  *
      4  * Copyright (c) 2020 Intel
      5  *
      6  * This work is licensed under the terms of the GNU GPL, version 2. See the
      7  * COPYING file in the top-level directory.
      8  */
      9 
     10 #ifndef CXL_COMPONENT_H
     11 #define CXL_COMPONENT_H
     12 
     13 /* CXL 2.0 - 8.2.4 */
     14 #define CXL2_COMPONENT_IO_REGION_SIZE 0x1000
     15 #define CXL2_COMPONENT_CM_REGION_SIZE 0x1000
     16 #define CXL2_COMPONENT_BLOCK_SIZE 0x10000
     17 
     18 #include "qemu/compiler.h"
     19 #include "qemu/range.h"
     20 #include "qemu/typedefs.h"
     21 #include "hw/register.h"
     22 #include "qapi/error.h"
     23 
     24 enum reg_type {
     25     CXL2_DEVICE,
     26     CXL2_TYPE3_DEVICE,
     27     CXL2_LOGICAL_DEVICE,
     28     CXL2_ROOT_PORT,
     29     CXL2_UPSTREAM_PORT,
     30     CXL2_DOWNSTREAM_PORT
     31 };
     32 
     33 /*
     34  * Capability registers are defined at the top of the CXL.cache/mem region and
     35  * are packed. For our purposes we will always define the caps in the same
     36  * order.
     37  * CXL 2.0 - 8.2.5 Table 142 for details.
     38  */
     39 
     40 /* CXL 2.0 - 8.2.5.1 */
     41 REG32(CXL_CAPABILITY_HEADER, 0)
     42     FIELD(CXL_CAPABILITY_HEADER, ID, 0, 16)
     43     FIELD(CXL_CAPABILITY_HEADER, VERSION, 16, 4)
     44     FIELD(CXL_CAPABILITY_HEADER, CACHE_MEM_VERSION, 20, 4)
     45     FIELD(CXL_CAPABILITY_HEADER, ARRAY_SIZE, 24, 8)
     46 
     47 #define CXLx_CAPABILITY_HEADER(type, offset)                  \
     48     REG32(CXL_##type##_CAPABILITY_HEADER, offset)             \
     49         FIELD(CXL_##type##_CAPABILITY_HEADER, ID, 0, 16)      \
     50         FIELD(CXL_##type##_CAPABILITY_HEADER, VERSION, 16, 4) \
     51         FIELD(CXL_##type##_CAPABILITY_HEADER, PTR, 20, 12)
     52 CXLx_CAPABILITY_HEADER(RAS, 0x4)
     53 CXLx_CAPABILITY_HEADER(LINK, 0x8)
     54 CXLx_CAPABILITY_HEADER(HDM, 0xc)
     55 CXLx_CAPABILITY_HEADER(EXTSEC, 0x10)
     56 CXLx_CAPABILITY_HEADER(SNOOP, 0x14)
     57 
     58 /*
     59  * Capability structures contain the actual registers that the CXL component
     60  * implements. Some of these are specific to certain types of components, but
     61  * this implementation leaves enough space regardless.
     62  */
     63 /* 8.2.5.9 - CXL RAS Capability Structure */
     64 
     65 /* Give ample space for caps before this */
     66 #define CXL_RAS_REGISTERS_OFFSET 0x80
     67 #define CXL_RAS_REGISTERS_SIZE   0x58
     68 REG32(CXL_RAS_UNC_ERR_STATUS, CXL_RAS_REGISTERS_OFFSET)
     69 REG32(CXL_RAS_UNC_ERR_MASK, CXL_RAS_REGISTERS_OFFSET + 0x4)
     70 REG32(CXL_RAS_UNC_ERR_SEVERITY, CXL_RAS_REGISTERS_OFFSET + 0x8)
     71 REG32(CXL_RAS_COR_ERR_STATUS, CXL_RAS_REGISTERS_OFFSET + 0xc)
     72 REG32(CXL_RAS_COR_ERR_MASK, CXL_RAS_REGISTERS_OFFSET + 0x10)
     73 REG32(CXL_RAS_ERR_CAP_CTRL, CXL_RAS_REGISTERS_OFFSET + 0x14)
     74 /* Offset 0x18 - 0x58 reserved for RAS logs */
     75 
     76 /* 8.2.5.10 - CXL Security Capability Structure */
     77 #define CXL_SEC_REGISTERS_OFFSET \
     78     (CXL_RAS_REGISTERS_OFFSET + CXL_RAS_REGISTERS_SIZE)
     79 #define CXL_SEC_REGISTERS_SIZE   0 /* We don't implement 1.1 downstream ports */
     80 
     81 /* 8.2.5.11 - CXL Link Capability Structure */
     82 #define CXL_LINK_REGISTERS_OFFSET \
     83     (CXL_SEC_REGISTERS_OFFSET + CXL_SEC_REGISTERS_SIZE)
     84 #define CXL_LINK_REGISTERS_SIZE   0x38
     85 
     86 /* 8.2.5.12 - CXL HDM Decoder Capability Structure */
     87 #define HDM_DECODE_MAX 10 /* 8.2.5.12.1 */
     88 #define CXL_HDM_REGISTERS_OFFSET \
     89     (CXL_LINK_REGISTERS_OFFSET + CXL_LINK_REGISTERS_SIZE)
     90 #define CXL_HDM_REGISTERS_SIZE (0x10 + 0x20 * HDM_DECODE_MAX)
     91 #define HDM_DECODER_INIT(n)                                                    \
     92   REG32(CXL_HDM_DECODER##n##_BASE_LO,                                          \
     93         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x10)                          \
     94             FIELD(CXL_HDM_DECODER##n##_BASE_LO, L, 28, 4)                      \
     95   REG32(CXL_HDM_DECODER##n##_BASE_HI,                                          \
     96         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x14)                          \
     97   REG32(CXL_HDM_DECODER##n##_SIZE_LO,                                          \
     98         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x18)                          \
     99   REG32(CXL_HDM_DECODER##n##_SIZE_HI,                                          \
    100         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x1C)                          \
    101   REG32(CXL_HDM_DECODER##n##_CTRL,                                             \
    102         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x20)                          \
    103             FIELD(CXL_HDM_DECODER##n##_CTRL, IG, 0, 4)                         \
    104             FIELD(CXL_HDM_DECODER##n##_CTRL, IW, 4, 4)                         \
    105             FIELD(CXL_HDM_DECODER##n##_CTRL, LOCK_ON_COMMIT, 8, 1)             \
    106             FIELD(CXL_HDM_DECODER##n##_CTRL, COMMIT, 9, 1)                     \
    107             FIELD(CXL_HDM_DECODER##n##_CTRL, COMMITTED, 10, 1)                 \
    108             FIELD(CXL_HDM_DECODER##n##_CTRL, ERR, 11, 1)                       \
    109             FIELD(CXL_HDM_DECODER##n##_CTRL, TYPE, 12, 1)                      \
    110   REG32(CXL_HDM_DECODER##n##_TARGET_LIST_LO,                                   \
    111         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x24)                          \
    112   REG32(CXL_HDM_DECODER##n##_TARGET_LIST_HI,                                   \
    113         CXL_HDM_REGISTERS_OFFSET + (0x20 * n) + 0x28)
    114 
    115 REG32(CXL_HDM_DECODER_CAPABILITY, CXL_HDM_REGISTERS_OFFSET)
    116     FIELD(CXL_HDM_DECODER_CAPABILITY, DECODER_COUNT, 0, 4)
    117     FIELD(CXL_HDM_DECODER_CAPABILITY, TARGET_COUNT, 4, 4)
    118     FIELD(CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_256B, 8, 1)
    119     FIELD(CXL_HDM_DECODER_CAPABILITY, INTERLEAVE_4K, 9, 1)
    120     FIELD(CXL_HDM_DECODER_CAPABILITY, POISON_ON_ERR_CAP, 10, 1)
    121 REG32(CXL_HDM_DECODER_GLOBAL_CONTROL, CXL_HDM_REGISTERS_OFFSET + 4)
    122     FIELD(CXL_HDM_DECODER_GLOBAL_CONTROL, POISON_ON_ERR_EN, 0, 1)
    123     FIELD(CXL_HDM_DECODER_GLOBAL_CONTROL, HDM_DECODER_ENABLE, 1, 1)
    124 
    125 HDM_DECODER_INIT(0);
    126 
    127 /* 8.2.5.13 - CXL Extended Security Capability Structure (Root complex only) */
    128 #define EXTSEC_ENTRY_MAX        256
    129 #define CXL_EXTSEC_REGISTERS_OFFSET \
    130     (CXL_HDM_REGISTERS_OFFSET + CXL_HDM_REGISTERS_SIZE)
    131 #define CXL_EXTSEC_REGISTERS_SIZE   (8 * EXTSEC_ENTRY_MAX + 4)
    132 
    133 /* 8.2.5.14 - CXL IDE Capability Structure */
    134 #define CXL_IDE_REGISTERS_OFFSET \
    135     (CXL_EXTSEC_REGISTERS_OFFSET + CXL_EXTSEC_REGISTERS_SIZE)
    136 #define CXL_IDE_REGISTERS_SIZE   0x20
    137 
    138 /* 8.2.5.15 - CXL Snoop Filter Capability Structure */
    139 #define CXL_SNOOP_REGISTERS_OFFSET \
    140     (CXL_IDE_REGISTERS_OFFSET + CXL_IDE_REGISTERS_SIZE)
    141 #define CXL_SNOOP_REGISTERS_SIZE   0x8
    142 
    143 QEMU_BUILD_BUG_MSG((CXL_SNOOP_REGISTERS_OFFSET + CXL_SNOOP_REGISTERS_SIZE) >= 0x1000,
    144                    "No space for registers");
    145 
    146 typedef struct component_registers {
    147     /*
    148      * Main memory region to be registered with QEMU core.
    149      */
    150     MemoryRegion component_registers;
    151 
    152     /*
    153      * 8.2.4 Table 141:
    154      *   0x0000 - 0x0fff CXL.io registers
    155      *   0x1000 - 0x1fff CXL.cache and CXL.mem
    156      *   0x2000 - 0xdfff Implementation specific
    157      *   0xe000 - 0xe3ff CXL ARB/MUX registers
    158      *   0xe400 - 0xffff RSVD
    159      */
    160     uint32_t io_registers[CXL2_COMPONENT_IO_REGION_SIZE >> 2];
    161     MemoryRegion io;
    162 
    163     uint32_t cache_mem_registers[CXL2_COMPONENT_CM_REGION_SIZE >> 2];
    164     uint32_t cache_mem_regs_write_mask[CXL2_COMPONENT_CM_REGION_SIZE >> 2];
    165     MemoryRegion cache_mem;
    166 
    167     MemoryRegion impl_specific;
    168     MemoryRegion arb_mux;
    169     MemoryRegion rsvd;
    170 
    171     /* special_ops is used for any component that needs any specific handling */
    172     MemoryRegionOps *special_ops;
    173 } ComponentRegisters;
    174 
    175 /*
    176  * A CXL component represents all entities in a CXL hierarchy. This includes,
    177  * host bridges, root ports, upstream/downstream switch ports, and devices
    178  */
    179 typedef struct cxl_component {
    180     ComponentRegisters crb;
    181     union {
    182         struct {
    183             Range dvsecs[CXL20_MAX_DVSEC];
    184             uint16_t dvsec_offset;
    185             struct PCIDevice *pdev;
    186         };
    187     };
    188 
    189     CDATObject cdat;
    190 } CXLComponentState;
    191 
    192 void cxl_component_register_block_init(Object *obj,
    193                                        CXLComponentState *cxl_cstate,
    194                                        const char *type);
    195 void cxl_component_register_init_common(uint32_t *reg_state,
    196                                         uint32_t *write_msk,
    197                                         enum reg_type type);
    198 
    199 void cxl_component_create_dvsec(CXLComponentState *cxl_cstate,
    200                                 enum reg_type cxl_dev_type, uint16_t length,
    201                                 uint16_t type, uint8_t rev, uint8_t *body);
    202 
    203 static inline int cxl_decoder_count_enc(int count)
    204 {
    205     switch (count) {
    206     case 1: return 0;
    207     case 2: return 1;
    208     case 4: return 2;
    209     case 6: return 3;
    210     case 8: return 4;
    211     case 10: return 5;
    212     }
    213     return 0;
    214 }
    215 
    216 uint8_t cxl_interleave_ways_enc(int iw, Error **errp);
    217 uint8_t cxl_interleave_granularity_enc(uint64_t gran, Error **errp);
    218 
    219 static inline hwaddr cxl_decode_ig(int ig)
    220 {
    221     return 1ULL << (ig + 8);
    222 }
    223 
    224 CXLComponentState *cxl_get_hb_cstate(PCIHostState *hb);
    225 
    226 void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp);
    227 void cxl_doe_cdat_release(CXLComponentState *cxl_cstate);
    228 void cxl_doe_cdat_update(CXLComponentState *cxl_cstate, Error **errp);
    229 
    230 #endif