On Tue, 10 Nov 2020 21:47:04 -0800 Ben Widawsky <ben.widaw...@intel.com> wrote:
> This implements all device MMIO up to the first capability .That > includes the CXL Device Capabilities Array Register, as well as all of > the CXL Device Capability Header Registers. The latter are filled in as > they are implemented in the following patches. > > Signed-off-by: Ben Widawsky <ben.widaw...@intel.com> Question below. Thanks, Jonathan > --- > hw/cxl/cxl-device-utils.c | 73 +++++++++++++++++++++++++++++++++++++++ > hw/cxl/meson.build | 1 + > 2 files changed, 74 insertions(+) > > diff --git a/hw/cxl/cxl-device-utils.c b/hw/cxl/cxl-device-utils.c > index e69de29bb2..a391bb15c6 100644 > --- a/hw/cxl/cxl-device-utils.c > +++ b/hw/cxl/cxl-device-utils.c > @@ -0,0 +1,73 @@ > +/* > + * CXL Utility library for devices > + * > + * Copyright(C) 2020 Intel Corporation. > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See the > + * COPYING file in the top-level directory. > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/log.h" > +#include "hw/cxl/cxl.h" > + > +static uint64_t caps_reg_read(void *opaque, hwaddr offset, unsigned size) > +{ > + CXLDeviceState *cxl_dstate = opaque; > + > + switch (size) { > + case 4: > + if (unlikely(offset & (sizeof(uint32_t) - 1))) { > + qemu_log_mask(LOG_UNIMP, "Unaligned register read\n"); > + return 0; > + } > + break; > + case 8: > + if (unlikely(offset & (sizeof(uint64_t) - 1))) { > + qemu_log_mask(LOG_UNIMP, "Unaligned register read\n"); > + return 0; > + } > + break; Seems unlikely but in theory we might get other sizes such as 2 and need that to be aligned? If we just don't want to support them perhaps a default with suitable error print is appropriate? > + } > + > + return ldn_le_p(cxl_dstate->caps_reg_state + offset, size); > +} > + > +static const MemoryRegionOps caps_ops = { > + .read = caps_reg_read, > + .write = NULL, > + .endianness = DEVICE_LITTLE_ENDIAN, > + .valid = { > + .min_access_size = 4, > + .max_access_size = 8, > + }, > + .impl = { > + .min_access_size = 4, > + .max_access_size = 8, > + }, > +}; > + > +void cxl_device_register_block_init(Object *obj, CXLDeviceState *cxl_dstate) > +{ > + /* This will be a BAR, so needs to be rounded up to pow2 for PCI spec */ > + memory_region_init( > + &cxl_dstate->device_registers, obj, "device-registers", > + pow2ceil(CXL_MAILBOX_REGISTERS_LENGTH + > CXL_MAILBOX_REGISTERS_OFFSET)); > + > + memory_region_init_io(&cxl_dstate->caps, obj, &caps_ops, cxl_dstate, > + "cap-array", CXL_DEVICE_REGISTERS_OFFSET - 0); > + > + memory_region_add_subregion(&cxl_dstate->device_registers, 0, > + &cxl_dstate->caps); > +} > + > +void cxl_device_register_init_common(CXLDeviceState *cxl_dstate) > +{ > + uint32_t *cap_hdrs = cxl_dstate->caps_reg_state32; > + const int cap_count = 0; > + > + /* CXL Device Capabilities Array Register */ > + ARRAY_FIELD_DP32(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_ID, 0); > + ARRAY_FIELD_DP32(cap_hdrs, CXL_DEV_CAP_ARRAY, CAP_VERSION, 1); > + ARRAY_FIELD_DP32(cap_hdrs, CXL_DEV_CAP_ARRAY2, CAP_COUNT, cap_count); > +} > diff --git a/hw/cxl/meson.build b/hw/cxl/meson.build > index 00c3876a0f..47154d6850 100644 > --- a/hw/cxl/meson.build > +++ b/hw/cxl/meson.build > @@ -1,3 +1,4 @@ > softmmu_ss.add(when: 'CONFIG_CXL', if_true: files( > 'cxl-component-utils.c', > + 'cxl-device-utils.c', > ))