1 /* 2 * s390 storage key device 3 * 4 * Copyright 2015 IBM Corp. 5 * Author(s): Jason J. Herne <jjherne@linux.vnet.ibm.com> 6 * 7 * This work is licensed under the terms of the GNU GPL, version 2 or (at 8 * your option) any later version. See the COPYING file in the top-level 9 * directory. 10 */ 11 12 #include "qemu/osdep.h" 13 #include "qemu/units.h" 14 #include "hw/s390x/s390-virtio-ccw.h" 15 #include "hw/qdev-properties.h" 16 #include "hw/s390x/storage-keys.h" 17 #include "qapi/error.h" 18 #include "qapi/qapi-commands-machine.h" 19 #include "qapi/qapi-commands-misc-target.h" 20 #include "qobject/qdict.h" 21 #include "qemu/error-report.h" 22 #include "system/memory_mapping.h" 23 #include "system/address-spaces.h" 24 #include "system/kvm.h" 25 #include "migration/qemu-file-types.h" 26 #include "migration/register.h" 27 #include "trace.h" 28 29 #define S390_SKEYS_BUFFER_SIZE (128 * KiB) /* Room for 128k storage keys */ 30 #define S390_SKEYS_SAVE_FLAG_EOS 0x01 31 #define S390_SKEYS_SAVE_FLAG_SKEYS 0x02 32 #define S390_SKEYS_SAVE_FLAG_ERROR 0x04 33 34 S390SKeysState *s390_get_skeys_device(void) 35 { 36 S390SKeysState *ss; 37 38 ss = S390_SKEYS(object_resolve_path_type("", TYPE_S390_SKEYS, NULL)); 39 assert(ss); 40 return ss; 41 } 42 43 void s390_skeys_init(void) 44 { 45 Object *obj; 46 47 if (kvm_enabled()) { 48 obj = object_new(TYPE_KVM_S390_SKEYS); 49 } else { 50 obj = object_new(TYPE_QEMU_S390_SKEYS); 51 } 52 object_property_add_child(qdev_get_machine(), TYPE_S390_SKEYS, 53 obj); 54 object_unref(obj); 55 56 qdev_realize(DEVICE(obj), NULL, &error_fatal); 57 } 58 59 int s390_skeys_get(S390SKeysState *ks, uint64_t start_gfn, 60 uint64_t count, uint8_t *keys) 61 { 62 S390SKeysClass *kc = S390_SKEYS_GET_CLASS(ks); 63 int rc; 64 65 rc = kc->get_skeys(ks, start_gfn, count, keys); 66 if (rc) { 67 trace_s390_skeys_get_nonzero(rc); 68 } 69 return rc; 70 } 71 72 int s390_skeys_set(S390SKeysState *ks, uint64_t start_gfn, 73 uint64_t count, uint8_t *keys) 74 { 75 S390SKeysClass *kc = S390_SKEYS_GET_CLASS(ks); 76 int rc; 77 78 rc = kc->set_skeys(ks, start_gfn, count, keys); 79 if (rc) { 80 trace_s390_skeys_set_nonzero(rc); 81 } 82 return rc; 83 } 84 85 static void write_keys(FILE *f, uint8_t *keys, uint64_t startgfn, 86 uint64_t count, Error **errp) 87 { 88 uint64_t curpage = startgfn; 89 uint64_t maxpage = curpage + count - 1; 90 91 for (; curpage <= maxpage; curpage++) { 92 uint8_t acc = (*keys & 0xF0) >> 4; 93 int fp = (*keys & 0x08); 94 int ref = (*keys & 0x04); 95 int ch = (*keys & 0x02); 96 int res = (*keys & 0x01); 97 98 fprintf(f, "page=%03" PRIx64 ": key(%d) => ACC=%X, FP=%d, REF=%d," 99 " ch=%d, reserved=%d\n", 100 curpage, *keys, acc, fp, ref, ch, res); 101 keys++; 102 } 103 } 104 105 void hmp_info_skeys(Monitor *mon, const QDict *qdict) 106 { 107 S390SKeysState *ss = s390_get_skeys_device(); 108 S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); 109 uint64_t addr = qdict_get_int(qdict, "addr"); 110 uint8_t key; 111 int r; 112 113 /* Quick check to see if guest is using storage keys*/ 114 if (!skeyclass->skeys_are_enabled(ss)) { 115 monitor_printf(mon, "Error: This guest is not using storage keys\n"); 116 return; 117 } 118 119 if (!address_space_access_valid(&address_space_memory, 120 addr & TARGET_PAGE_MASK, TARGET_PAGE_SIZE, 121 false, MEMTXATTRS_UNSPECIFIED)) { 122 monitor_printf(mon, "Error: The given address is not valid\n"); 123 return; 124 } 125 126 r = skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key); 127 if (r < 0) { 128 monitor_printf(mon, "Error: %s\n", strerror(-r)); 129 return; 130 } 131 132 monitor_printf(mon, " key: 0x%X\n", key); 133 } 134 135 void hmp_dump_skeys(Monitor *mon, const QDict *qdict) 136 { 137 const char *filename = qdict_get_str(qdict, "filename"); 138 Error *err = NULL; 139 140 qmp_dump_skeys(filename, &err); 141 if (err) { 142 error_report_err(err); 143 } 144 } 145 146 void s390_qmp_dump_skeys(const char *filename, Error **errp) 147 { 148 S390SKeysState *ss = s390_get_skeys_device(); 149 S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); 150 GuestPhysBlockList guest_phys_blocks; 151 GuestPhysBlock *block; 152 uint64_t pages, gfn; 153 Error *lerr = NULL; 154 uint8_t *buf; 155 int ret; 156 int fd; 157 FILE *f; 158 159 /* Quick check to see if guest is using storage keys*/ 160 if (!skeyclass->skeys_are_enabled(ss)) { 161 error_setg(errp, "This guest is not using storage keys - " 162 "nothing to dump"); 163 return; 164 } 165 166 fd = qemu_open_old(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600); 167 if (fd < 0) { 168 error_setg_file_open(errp, errno, filename); 169 return; 170 } 171 f = fdopen(fd, "wb"); 172 if (!f) { 173 close(fd); 174 error_setg_file_open(errp, errno, filename); 175 return; 176 } 177 178 buf = g_try_malloc(S390_SKEYS_BUFFER_SIZE); 179 if (!buf) { 180 error_setg(errp, "Could not allocate memory"); 181 goto out; 182 } 183 184 assert(bql_locked()); 185 guest_phys_blocks_init(&guest_phys_blocks); 186 guest_phys_blocks_append(&guest_phys_blocks); 187 188 QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) { 189 assert(QEMU_IS_ALIGNED(block->target_start, TARGET_PAGE_SIZE)); 190 assert(QEMU_IS_ALIGNED(block->target_end, TARGET_PAGE_SIZE)); 191 192 gfn = block->target_start / TARGET_PAGE_SIZE; 193 pages = (block->target_end - block->target_start) / TARGET_PAGE_SIZE; 194 195 while (pages) { 196 const uint64_t cur_pages = MIN(pages, S390_SKEYS_BUFFER_SIZE); 197 198 ret = skeyclass->get_skeys(ss, gfn, cur_pages, buf); 199 if (ret < 0) { 200 error_setg_errno(errp, -ret, "get_keys error"); 201 goto out_free; 202 } 203 204 /* write keys to stream */ 205 write_keys(f, buf, gfn, cur_pages, &lerr); 206 if (lerr) { 207 goto out_free; 208 } 209 210 gfn += cur_pages; 211 pages -= cur_pages; 212 } 213 } 214 215 out_free: 216 guest_phys_blocks_free(&guest_phys_blocks); 217 error_propagate(errp, lerr); 218 g_free(buf); 219 out: 220 fclose(f); 221 } 222 223 static bool qemu_s390_skeys_are_enabled(S390SKeysState *ss) 224 { 225 QEMUS390SKeysState *skeys = QEMU_S390_SKEYS(ss); 226 227 /* Lockless check is sufficient. */ 228 return !!skeys->keydata; 229 } 230 231 static bool qemu_s390_enable_skeys(S390SKeysState *ss) 232 { 233 QEMUS390SKeysState *skeys = QEMU_S390_SKEYS(ss); 234 static gsize initialized; 235 236 if (likely(skeys->keydata)) { 237 return true; 238 } 239 240 /* 241 * TODO: Modern Linux doesn't use storage keys unless running KVM guests 242 * that use storage keys. Therefore, we keep it simple for now. 243 * 244 * 1) We should initialize to "referenced+changed" for an initial 245 * over-indication. Let's avoid touching megabytes of data for now and 246 * assume that any sane user will issue a storage key instruction before 247 * actually relying on this data. 248 * 2) Relying on ram_size and allocating a big array is ugly. We should 249 * allocate and manage storage key data per RAMBlock or optimally using 250 * some sparse data structure. 251 * 3) We only ever have a single S390SKeysState, so relying on 252 * g_once_init_enter() is good enough. 253 */ 254 if (g_once_init_enter(&initialized)) { 255 S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine()); 256 257 skeys->key_count = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE; 258 skeys->keydata = g_malloc0(skeys->key_count); 259 g_once_init_leave(&initialized, 1); 260 } 261 return false; 262 } 263 264 static int qemu_s390_skeys_set(S390SKeysState *ss, uint64_t start_gfn, 265 uint64_t count, uint8_t *keys) 266 { 267 QEMUS390SKeysState *skeydev = QEMU_S390_SKEYS(ss); 268 int i; 269 270 /* Check for uint64 overflow and access beyond end of key data */ 271 if (unlikely(!skeydev->keydata || start_gfn + count > skeydev->key_count || 272 start_gfn + count < count)) { 273 error_report("Error: Setting storage keys for pages with unallocated " 274 "storage key memory: gfn=%" PRIx64 " count=%" PRId64, 275 start_gfn, count); 276 return -EINVAL; 277 } 278 279 for (i = 0; i < count; i++) { 280 skeydev->keydata[start_gfn + i] = keys[i]; 281 } 282 return 0; 283 } 284 285 static int qemu_s390_skeys_get(S390SKeysState *ss, uint64_t start_gfn, 286 uint64_t count, uint8_t *keys) 287 { 288 QEMUS390SKeysState *skeydev = QEMU_S390_SKEYS(ss); 289 int i; 290 291 /* Check for uint64 overflow and access beyond end of key data */ 292 if (unlikely(!skeydev->keydata || start_gfn + count > skeydev->key_count || 293 start_gfn + count < count)) { 294 error_report("Error: Getting storage keys for pages with unallocated " 295 "storage key memory: gfn=%" PRIx64 " count=%" PRId64, 296 start_gfn, count); 297 return -EINVAL; 298 } 299 300 for (i = 0; i < count; i++) { 301 keys[i] = skeydev->keydata[start_gfn + i]; 302 } 303 return 0; 304 } 305 306 static void qemu_s390_skeys_class_init(ObjectClass *oc, void *data) 307 { 308 S390SKeysClass *skeyclass = S390_SKEYS_CLASS(oc); 309 DeviceClass *dc = DEVICE_CLASS(oc); 310 311 skeyclass->skeys_are_enabled = qemu_s390_skeys_are_enabled; 312 skeyclass->enable_skeys = qemu_s390_enable_skeys; 313 skeyclass->get_skeys = qemu_s390_skeys_get; 314 skeyclass->set_skeys = qemu_s390_skeys_set; 315 316 /* Reason: Internal device (only one skeys device for the whole memory) */ 317 dc->user_creatable = false; 318 } 319 320 static void s390_storage_keys_save(QEMUFile *f, void *opaque) 321 { 322 S390SKeysState *ss = S390_SKEYS(opaque); 323 S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); 324 GuestPhysBlockList guest_phys_blocks; 325 GuestPhysBlock *block; 326 uint64_t pages, gfn; 327 int error = 0; 328 uint8_t *buf; 329 330 if (!skeyclass->skeys_are_enabled(ss)) { 331 goto end_stream; 332 } 333 334 buf = g_try_malloc(S390_SKEYS_BUFFER_SIZE); 335 if (!buf) { 336 error_report("storage key save could not allocate memory"); 337 goto end_stream; 338 } 339 340 guest_phys_blocks_init(&guest_phys_blocks); 341 guest_phys_blocks_append(&guest_phys_blocks); 342 343 /* Send each contiguous physical memory range separately. */ 344 QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) { 345 assert(QEMU_IS_ALIGNED(block->target_start, TARGET_PAGE_SIZE)); 346 assert(QEMU_IS_ALIGNED(block->target_end, TARGET_PAGE_SIZE)); 347 348 gfn = block->target_start / TARGET_PAGE_SIZE; 349 pages = (block->target_end - block->target_start) / TARGET_PAGE_SIZE; 350 qemu_put_be64(f, block->target_start | S390_SKEYS_SAVE_FLAG_SKEYS); 351 qemu_put_be64(f, pages); 352 353 while (pages) { 354 const uint64_t cur_pages = MIN(pages, S390_SKEYS_BUFFER_SIZE); 355 356 if (!error) { 357 error = skeyclass->get_skeys(ss, gfn, cur_pages, buf); 358 if (error) { 359 /* 360 * Create a valid stream with all 0x00 and indicate 361 * S390_SKEYS_SAVE_FLAG_ERROR to the destination. 362 */ 363 error_report("S390_GET_KEYS error %d", error); 364 memset(buf, 0, S390_SKEYS_BUFFER_SIZE); 365 } 366 } 367 368 qemu_put_buffer(f, buf, cur_pages); 369 gfn += cur_pages; 370 pages -= cur_pages; 371 } 372 373 if (error) { 374 break; 375 } 376 } 377 378 guest_phys_blocks_free(&guest_phys_blocks); 379 g_free(buf); 380 end_stream: 381 if (error) { 382 qemu_put_be64(f, S390_SKEYS_SAVE_FLAG_ERROR); 383 } else { 384 qemu_put_be64(f, S390_SKEYS_SAVE_FLAG_EOS); 385 } 386 } 387 388 static int s390_storage_keys_load(QEMUFile *f, void *opaque, int version_id) 389 { 390 S390SKeysState *ss = S390_SKEYS(opaque); 391 S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); 392 int ret = 0; 393 394 /* 395 * Make sure to lazy-enable if required to be done explicitly. No need to 396 * flush any TLB as the VM is not running yet. 397 */ 398 if (skeyclass->enable_skeys) { 399 skeyclass->enable_skeys(ss); 400 } 401 402 while (!ret) { 403 ram_addr_t addr; 404 int flags; 405 406 addr = qemu_get_be64(f); 407 flags = addr & ~TARGET_PAGE_MASK; 408 addr &= TARGET_PAGE_MASK; 409 410 switch (flags) { 411 case S390_SKEYS_SAVE_FLAG_SKEYS: { 412 const uint64_t total_count = qemu_get_be64(f); 413 uint64_t handled_count = 0, cur_count; 414 uint64_t cur_gfn = addr / TARGET_PAGE_SIZE; 415 uint8_t *buf = g_try_malloc(S390_SKEYS_BUFFER_SIZE); 416 417 if (!buf) { 418 error_report("storage key load could not allocate memory"); 419 ret = -ENOMEM; 420 break; 421 } 422 423 while (handled_count < total_count) { 424 cur_count = MIN(total_count - handled_count, 425 S390_SKEYS_BUFFER_SIZE); 426 qemu_get_buffer(f, buf, cur_count); 427 428 ret = skeyclass->set_skeys(ss, cur_gfn, cur_count, buf); 429 if (ret < 0) { 430 error_report("S390_SET_KEYS error %d", ret); 431 break; 432 } 433 handled_count += cur_count; 434 cur_gfn += cur_count; 435 } 436 g_free(buf); 437 break; 438 } 439 case S390_SKEYS_SAVE_FLAG_ERROR: { 440 error_report("Storage key data is incomplete"); 441 ret = -EINVAL; 442 break; 443 } 444 case S390_SKEYS_SAVE_FLAG_EOS: 445 /* normal exit */ 446 return 0; 447 default: 448 error_report("Unexpected storage key flag data: %#x", flags); 449 ret = -EINVAL; 450 } 451 } 452 453 return ret; 454 } 455 456 static SaveVMHandlers savevm_s390_storage_keys = { 457 .save_state = s390_storage_keys_save, 458 .load_state = s390_storage_keys_load, 459 }; 460 461 static void s390_skeys_realize(DeviceState *dev, Error **errp) 462 { 463 S390SKeysState *ss = S390_SKEYS(dev); 464 465 register_savevm_live(TYPE_S390_SKEYS, 0, 1, &savevm_s390_storage_keys, ss); 466 } 467 468 static void s390_skeys_class_init(ObjectClass *oc, void *data) 469 { 470 DeviceClass *dc = DEVICE_CLASS(oc); 471 472 dc->hotpluggable = false; 473 dc->realize = s390_skeys_realize; 474 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 475 } 476 477 static const TypeInfo s390_skeys_types[] = { 478 { 479 .name = TYPE_DUMP_SKEYS_INTERFACE, 480 .parent = TYPE_INTERFACE, 481 .class_size = sizeof(DumpSKeysInterface), 482 }, 483 { 484 .name = TYPE_S390_SKEYS, 485 .parent = TYPE_DEVICE, 486 .instance_size = sizeof(S390SKeysState), 487 .class_init = s390_skeys_class_init, 488 .class_size = sizeof(S390SKeysClass), 489 .abstract = true, 490 }, 491 { 492 .name = TYPE_QEMU_S390_SKEYS, 493 .parent = TYPE_S390_SKEYS, 494 .instance_size = sizeof(QEMUS390SKeysState), 495 .class_init = qemu_s390_skeys_class_init, 496 .class_size = sizeof(S390SKeysClass), 497 }, 498 }; 499 500 DEFINE_TYPES(s390_skeys_types) 501