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