1 /* 2 * QEMU PAPR Storage Class Memory Interfaces 3 * 4 * Copyright (c) 2019-2020, IBM Corporation. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 #include "qemu/osdep.h" 25 #include "qapi/error.h" 26 #include "hw/ppc/spapr_drc.h" 27 #include "hw/ppc/spapr_nvdimm.h" 28 #include "hw/mem/nvdimm.h" 29 #include "qemu/nvdimm-utils.h" 30 #include "hw/ppc/fdt.h" 31 #include "qemu/range.h" 32 #include "hw/ppc/spapr_numa.h" 33 34 bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm, 35 uint64_t size, Error **errp) 36 { 37 const MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 38 const MachineState *ms = MACHINE(hotplug_dev); 39 g_autofree char *uuidstr = NULL; 40 QemuUUID uuid; 41 int ret; 42 43 if (!mc->nvdimm_supported) { 44 error_setg(errp, "NVDIMM hotplug not supported for this machine"); 45 return false; 46 } 47 48 if (!ms->nvdimms_state->is_enabled) { 49 error_setg(errp, "nvdimm device found but 'nvdimm=off' was set"); 50 return false; 51 } 52 53 if (object_property_get_int(OBJECT(nvdimm), NVDIMM_LABEL_SIZE_PROP, 54 &error_abort) == 0) { 55 error_setg(errp, "PAPR requires NVDIMM devices to have label-size set"); 56 return false; 57 } 58 59 if (size % SPAPR_MINIMUM_SCM_BLOCK_SIZE) { 60 error_setg(errp, "PAPR requires NVDIMM memory size (excluding label)" 61 " to be a multiple of %" PRIu64 "MB", 62 SPAPR_MINIMUM_SCM_BLOCK_SIZE / MiB); 63 return false; 64 } 65 66 uuidstr = object_property_get_str(OBJECT(nvdimm), NVDIMM_UUID_PROP, 67 &error_abort); 68 ret = qemu_uuid_parse(uuidstr, &uuid); 69 g_assert(!ret); 70 71 if (qemu_uuid_is_null(&uuid)) { 72 error_setg(errp, "NVDIMM device requires the uuid to be set"); 73 return false; 74 } 75 76 return true; 77 } 78 79 80 void spapr_add_nvdimm(DeviceState *dev, uint64_t slot) 81 { 82 SpaprDrc *drc; 83 bool hotplugged = spapr_drc_hotplugged(dev); 84 85 drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PMEM, slot); 86 g_assert(drc); 87 88 /* 89 * pc_dimm_get_free_slot() provided a free slot at pre-plug. The 90 * corresponding DRC is thus assumed to be attachable. 91 */ 92 spapr_drc_attach(drc, dev); 93 94 if (hotplugged) { 95 spapr_hotplug_req_add_by_index(drc); 96 } 97 } 98 99 static int spapr_dt_nvdimm(SpaprMachineState *spapr, void *fdt, 100 int parent_offset, NVDIMMDevice *nvdimm) 101 { 102 int child_offset; 103 char *buf; 104 SpaprDrc *drc; 105 uint32_t drc_idx; 106 uint32_t node = object_property_get_uint(OBJECT(nvdimm), PC_DIMM_NODE_PROP, 107 &error_abort); 108 uint64_t slot = object_property_get_uint(OBJECT(nvdimm), PC_DIMM_SLOT_PROP, 109 &error_abort); 110 uint64_t lsize = nvdimm->label_size; 111 uint64_t size = object_property_get_int(OBJECT(nvdimm), PC_DIMM_SIZE_PROP, 112 NULL); 113 114 drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PMEM, slot); 115 g_assert(drc); 116 117 drc_idx = spapr_drc_index(drc); 118 119 buf = g_strdup_printf("ibm,pmemory@%x", drc_idx); 120 child_offset = fdt_add_subnode(fdt, parent_offset, buf); 121 g_free(buf); 122 123 _FDT(child_offset); 124 125 _FDT((fdt_setprop_cell(fdt, child_offset, "reg", drc_idx))); 126 _FDT((fdt_setprop_string(fdt, child_offset, "compatible", "ibm,pmemory"))); 127 _FDT((fdt_setprop_string(fdt, child_offset, "device_type", "ibm,pmemory"))); 128 129 spapr_numa_write_associativity_dt(spapr, fdt, child_offset, node); 130 131 buf = qemu_uuid_unparse_strdup(&nvdimm->uuid); 132 _FDT((fdt_setprop_string(fdt, child_offset, "ibm,unit-guid", buf))); 133 g_free(buf); 134 135 _FDT((fdt_setprop_cell(fdt, child_offset, "ibm,my-drc-index", drc_idx))); 136 137 _FDT((fdt_setprop_u64(fdt, child_offset, "ibm,block-size", 138 SPAPR_MINIMUM_SCM_BLOCK_SIZE))); 139 _FDT((fdt_setprop_u64(fdt, child_offset, "ibm,number-of-blocks", 140 size / SPAPR_MINIMUM_SCM_BLOCK_SIZE))); 141 _FDT((fdt_setprop_cell(fdt, child_offset, "ibm,metadata-size", lsize))); 142 143 _FDT((fdt_setprop_string(fdt, child_offset, "ibm,pmem-application", 144 "operating-system"))); 145 _FDT(fdt_setprop(fdt, child_offset, "ibm,cache-flush-required", NULL, 0)); 146 147 return child_offset; 148 } 149 150 int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, 151 void *fdt, int *fdt_start_offset, Error **errp) 152 { 153 NVDIMMDevice *nvdimm = NVDIMM(drc->dev); 154 155 *fdt_start_offset = spapr_dt_nvdimm(spapr, fdt, 0, nvdimm); 156 157 return 0; 158 } 159 160 void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt) 161 { 162 int offset = fdt_subnode_offset(fdt, 0, "persistent-memory"); 163 GSList *iter, *nvdimms = nvdimm_get_device_list(); 164 165 if (offset < 0) { 166 offset = fdt_add_subnode(fdt, 0, "persistent-memory"); 167 _FDT(offset); 168 _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0x1))); 169 _FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 0x0))); 170 _FDT((fdt_setprop_string(fdt, offset, "device_type", 171 "ibm,persistent-memory"))); 172 } 173 174 /* Create DT entries for cold plugged NVDIMM devices */ 175 for (iter = nvdimms; iter; iter = iter->next) { 176 NVDIMMDevice *nvdimm = iter->data; 177 178 spapr_dt_nvdimm(spapr, fdt, offset, nvdimm); 179 } 180 g_slist_free(nvdimms); 181 182 return; 183 } 184 185 static target_ulong h_scm_read_metadata(PowerPCCPU *cpu, 186 SpaprMachineState *spapr, 187 target_ulong opcode, 188 target_ulong *args) 189 { 190 uint32_t drc_index = args[0]; 191 uint64_t offset = args[1]; 192 uint64_t len = args[2]; 193 SpaprDrc *drc = spapr_drc_by_index(drc_index); 194 NVDIMMDevice *nvdimm; 195 NVDIMMClass *ddc; 196 uint64_t data = 0; 197 uint8_t buf[8] = { 0 }; 198 199 if (!drc || !drc->dev || 200 spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PMEM) { 201 return H_PARAMETER; 202 } 203 204 if (len != 1 && len != 2 && 205 len != 4 && len != 8) { 206 return H_P3; 207 } 208 209 nvdimm = NVDIMM(drc->dev); 210 if ((offset + len < offset) || 211 (nvdimm->label_size < len + offset)) { 212 return H_P2; 213 } 214 215 ddc = NVDIMM_GET_CLASS(nvdimm); 216 ddc->read_label_data(nvdimm, buf, len, offset); 217 218 switch (len) { 219 case 1: 220 data = ldub_p(buf); 221 break; 222 case 2: 223 data = lduw_be_p(buf); 224 break; 225 case 4: 226 data = ldl_be_p(buf); 227 break; 228 case 8: 229 data = ldq_be_p(buf); 230 break; 231 default: 232 g_assert_not_reached(); 233 } 234 235 args[0] = data; 236 237 return H_SUCCESS; 238 } 239 240 static target_ulong h_scm_write_metadata(PowerPCCPU *cpu, 241 SpaprMachineState *spapr, 242 target_ulong opcode, 243 target_ulong *args) 244 { 245 uint32_t drc_index = args[0]; 246 uint64_t offset = args[1]; 247 uint64_t data = args[2]; 248 uint64_t len = args[3]; 249 SpaprDrc *drc = spapr_drc_by_index(drc_index); 250 NVDIMMDevice *nvdimm; 251 NVDIMMClass *ddc; 252 uint8_t buf[8] = { 0 }; 253 254 if (!drc || !drc->dev || 255 spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PMEM) { 256 return H_PARAMETER; 257 } 258 259 if (len != 1 && len != 2 && 260 len != 4 && len != 8) { 261 return H_P4; 262 } 263 264 nvdimm = NVDIMM(drc->dev); 265 if ((offset + len < offset) || 266 (nvdimm->label_size < len + offset)) { 267 return H_P2; 268 } 269 270 switch (len) { 271 case 1: 272 if (data & 0xffffffffffffff00) { 273 return H_P2; 274 } 275 stb_p(buf, data); 276 break; 277 case 2: 278 if (data & 0xffffffffffff0000) { 279 return H_P2; 280 } 281 stw_be_p(buf, data); 282 break; 283 case 4: 284 if (data & 0xffffffff00000000) { 285 return H_P2; 286 } 287 stl_be_p(buf, data); 288 break; 289 case 8: 290 stq_be_p(buf, data); 291 break; 292 default: 293 g_assert_not_reached(); 294 } 295 296 ddc = NVDIMM_GET_CLASS(nvdimm); 297 ddc->write_label_data(nvdimm, buf, len, offset); 298 299 return H_SUCCESS; 300 } 301 302 static target_ulong h_scm_bind_mem(PowerPCCPU *cpu, SpaprMachineState *spapr, 303 target_ulong opcode, target_ulong *args) 304 { 305 uint32_t drc_index = args[0]; 306 uint64_t starting_idx = args[1]; 307 uint64_t no_of_scm_blocks_to_bind = args[2]; 308 uint64_t target_logical_mem_addr = args[3]; 309 uint64_t continue_token = args[4]; 310 uint64_t size; 311 uint64_t total_no_of_scm_blocks; 312 SpaprDrc *drc = spapr_drc_by_index(drc_index); 313 hwaddr addr; 314 NVDIMMDevice *nvdimm; 315 316 if (!drc || !drc->dev || 317 spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PMEM) { 318 return H_PARAMETER; 319 } 320 321 /* 322 * Currently continue token should be zero qemu has already bound 323 * everything and this hcall doesnt return H_BUSY. 324 */ 325 if (continue_token > 0) { 326 return H_P5; 327 } 328 329 /* Currently qemu assigns the address. */ 330 if (target_logical_mem_addr != 0xffffffffffffffff) { 331 return H_OVERLAP; 332 } 333 334 nvdimm = NVDIMM(drc->dev); 335 336 size = object_property_get_uint(OBJECT(nvdimm), 337 PC_DIMM_SIZE_PROP, &error_abort); 338 339 total_no_of_scm_blocks = size / SPAPR_MINIMUM_SCM_BLOCK_SIZE; 340 341 if (starting_idx > total_no_of_scm_blocks) { 342 return H_P2; 343 } 344 345 if (((starting_idx + no_of_scm_blocks_to_bind) < starting_idx) || 346 ((starting_idx + no_of_scm_blocks_to_bind) > total_no_of_scm_blocks)) { 347 return H_P3; 348 } 349 350 addr = object_property_get_uint(OBJECT(nvdimm), 351 PC_DIMM_ADDR_PROP, &error_abort); 352 353 addr += starting_idx * SPAPR_MINIMUM_SCM_BLOCK_SIZE; 354 355 /* Already bound, Return target logical address in R5 */ 356 args[1] = addr; 357 args[2] = no_of_scm_blocks_to_bind; 358 359 return H_SUCCESS; 360 } 361 362 static target_ulong h_scm_unbind_mem(PowerPCCPU *cpu, SpaprMachineState *spapr, 363 target_ulong opcode, target_ulong *args) 364 { 365 uint32_t drc_index = args[0]; 366 uint64_t starting_scm_logical_addr = args[1]; 367 uint64_t no_of_scm_blocks_to_unbind = args[2]; 368 uint64_t continue_token = args[3]; 369 uint64_t size_to_unbind; 370 Range blockrange = range_empty; 371 Range nvdimmrange = range_empty; 372 SpaprDrc *drc = spapr_drc_by_index(drc_index); 373 NVDIMMDevice *nvdimm; 374 uint64_t size, addr; 375 376 if (!drc || !drc->dev || 377 spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PMEM) { 378 return H_PARAMETER; 379 } 380 381 /* continue_token should be zero as this hcall doesn't return H_BUSY. */ 382 if (continue_token > 0) { 383 return H_P4; 384 } 385 386 /* Check if starting_scm_logical_addr is block aligned */ 387 if (!QEMU_IS_ALIGNED(starting_scm_logical_addr, 388 SPAPR_MINIMUM_SCM_BLOCK_SIZE)) { 389 return H_P2; 390 } 391 392 size_to_unbind = no_of_scm_blocks_to_unbind * SPAPR_MINIMUM_SCM_BLOCK_SIZE; 393 if (no_of_scm_blocks_to_unbind == 0 || no_of_scm_blocks_to_unbind != 394 size_to_unbind / SPAPR_MINIMUM_SCM_BLOCK_SIZE) { 395 return H_P3; 396 } 397 398 nvdimm = NVDIMM(drc->dev); 399 size = object_property_get_int(OBJECT(nvdimm), PC_DIMM_SIZE_PROP, 400 &error_abort); 401 addr = object_property_get_int(OBJECT(nvdimm), PC_DIMM_ADDR_PROP, 402 &error_abort); 403 404 range_init_nofail(&nvdimmrange, addr, size); 405 range_init_nofail(&blockrange, starting_scm_logical_addr, size_to_unbind); 406 407 if (!range_contains_range(&nvdimmrange, &blockrange)) { 408 return H_P3; 409 } 410 411 args[1] = no_of_scm_blocks_to_unbind; 412 413 /* let unplug take care of actual unbind */ 414 return H_SUCCESS; 415 } 416 417 #define H_UNBIND_SCOPE_ALL 0x1 418 #define H_UNBIND_SCOPE_DRC 0x2 419 420 static target_ulong h_scm_unbind_all(PowerPCCPU *cpu, SpaprMachineState *spapr, 421 target_ulong opcode, target_ulong *args) 422 { 423 uint64_t target_scope = args[0]; 424 uint32_t drc_index = args[1]; 425 uint64_t continue_token = args[2]; 426 NVDIMMDevice *nvdimm; 427 uint64_t size; 428 uint64_t no_of_scm_blocks_unbound = 0; 429 430 /* continue_token should be zero as this hcall doesn't return H_BUSY. */ 431 if (continue_token > 0) { 432 return H_P4; 433 } 434 435 if (target_scope == H_UNBIND_SCOPE_DRC) { 436 SpaprDrc *drc = spapr_drc_by_index(drc_index); 437 438 if (!drc || !drc->dev || 439 spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PMEM) { 440 return H_P2; 441 } 442 443 nvdimm = NVDIMM(drc->dev); 444 size = object_property_get_int(OBJECT(nvdimm), PC_DIMM_SIZE_PROP, 445 &error_abort); 446 447 no_of_scm_blocks_unbound = size / SPAPR_MINIMUM_SCM_BLOCK_SIZE; 448 } else if (target_scope == H_UNBIND_SCOPE_ALL) { 449 GSList *list, *nvdimms; 450 451 nvdimms = nvdimm_get_device_list(); 452 for (list = nvdimms; list; list = list->next) { 453 nvdimm = list->data; 454 size = object_property_get_int(OBJECT(nvdimm), PC_DIMM_SIZE_PROP, 455 &error_abort); 456 457 no_of_scm_blocks_unbound += size / SPAPR_MINIMUM_SCM_BLOCK_SIZE; 458 } 459 g_slist_free(nvdimms); 460 } else { 461 return H_PARAMETER; 462 } 463 464 args[1] = no_of_scm_blocks_unbound; 465 466 /* let unplug take care of actual unbind */ 467 return H_SUCCESS; 468 } 469 470 static void spapr_scm_register_types(void) 471 { 472 /* qemu/scm specific hcalls */ 473 spapr_register_hypercall(H_SCM_READ_METADATA, h_scm_read_metadata); 474 spapr_register_hypercall(H_SCM_WRITE_METADATA, h_scm_write_metadata); 475 spapr_register_hypercall(H_SCM_BIND_MEM, h_scm_bind_mem); 476 spapr_register_hypercall(H_SCM_UNBIND_MEM, h_scm_unbind_mem); 477 spapr_register_hypercall(H_SCM_UNBIND_ALL, h_scm_unbind_all); 478 } 479 480 type_init(spapr_scm_register_types) 481