| 1 | |
| 2 | |
| 3 | * Common Ultravisor functions and initialization
|
| 4 | *
|
| 5 | * Copyright IBM Corp. 2019, 2024
|
| 6 |
|
| 7 | #define pr_fmt(fmt) "prot_virt: " fmt
|
| 8 |
|
| 9 | #include <linux/export.h>
|
| 10 | #include <linux/kernel.h>
|
| 11 | #include <linux/types.h>
|
| 12 | #include <linux/sizes.h>
|
| 13 | #include <linux/bitmap.h>
|
| 14 | #include <linux/memblock.h>
|
| 15 | #include <linux/pagemap.h>
|
| 16 | #include <linux/swap.h>
|
| 17 | #include <linux/pagewalk.h>
|
| 18 | #include <linux/backing-dev.h>
|
| 19 | #include <linux/vmalloc.h>
|
| 20 | #include <asm/facility.h>
|
| 21 | #include <asm/sections.h>
|
| 22 | #include <asm/uv.h>
|
| 23 |
|
| 24 |
|
| 25 | int __bootdata_preserved(prot_virt_guest);
|
| 26 | EXPORT_SYMBOL(prot_virt_guest);
|
| 27 |
|
| 28 | |
| 29 | * uv_info contains both host and guest information but it's currently only
|
| 30 | * expected to be used within modules if it's the KVM module or for
|
| 31 | * any PV guest module.
|
| 32 | *
|
| 33 | * The kernel itself will write these values once in uv_query_info()
|
| 34 | * and then make some of them readable via a sysfs interface.
|
| 35 |
|
| 36 | struct uv_info __bootdata_preserved(uv_info);
|
| 37 | EXPORT_SYMBOL(uv_info);
|
| 38 |
|
| 39 | int __bootdata_preserved(prot_virt_host);
|
| 40 | EXPORT_SYMBOL(prot_virt_host);
|
| 41 |
|
| 42 | static int __init uv_init(phys_addr_t stor_base, unsigned long stor_len)
|
| 43 | {
|
| 44 | struct uv_cb_init uvcb = {
|
| 45 | .header.cmd = UVC_CMD_INIT_UV,
|
| 46 | .header.len = sizeof(uvcb),
|
| 47 | .stor_origin = stor_base,
|
| 48 | .stor_len = stor_len,
|
| 49 | };
|
| 50 |
|
| 51 | if (uv_call(0, (uint64_t)&uvcb)) {
|
| 52 | pr_err("Ultravisor init failed with rc: 0x%x rrc: 0%x\n",
|
| 53 | uvcb.header.rc, uvcb.header.rrc);
|
| 54 | return -1;
|
| 55 | }
|
| 56 | return 0;
|
| 57 | }
|
| 58 |
|
| 59 | void __init setup_uv(void)
|
| 60 | {
|
| 61 | void *uv_stor_base;
|
| 62 |
|
| 63 | if (!is_prot_virt_host())
|
| 64 | return;
|
| 65 |
|
| 66 | uv_stor_base = memblock_alloc_try_nid(
|
| 67 | uv_info.uv_base_stor_len, SZ_1M, SZ_2G,
|
| 68 | MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);
|
| 69 | if (!uv_stor_base) {
|
| 70 | pr_warn("Failed to reserve %lu bytes for ultravisor base storage\n",
|
| 71 | uv_info.uv_base_stor_len);
|
| 72 | goto fail;
|
| 73 | }
|
| 74 |
|
| 75 | if (uv_init(__pa(uv_stor_base), uv_info.uv_base_stor_len)) {
|
| 76 | memblock_free(uv_stor_base, uv_info.uv_base_stor_len);
|
| 77 | goto fail;
|
| 78 | }
|
| 79 |
|
| 80 | pr_info("Reserving %luMB as ultravisor base storage\n",
|
| 81 | uv_info.uv_base_stor_len >> 20);
|
| 82 | return;
|
| 83 | fail:
|
| 84 | pr_info("Disabling support for protected virtualization");
|
| 85 | prot_virt_host = 0;
|
| 86 | }
|
| 87 |
|
| 88 | |
| 89 | * Requests the Ultravisor to pin the page in the shared state. This will
|
| 90 | * cause an intercept when the guest attempts to unshare the pinned page.
|
| 91 |
|
| 92 | int uv_pin_shared(unsigned long paddr)
|
| 93 | {
|
| 94 | struct uv_cb_cfs uvcb = {
|
| 95 | .header.cmd = UVC_CMD_PIN_PAGE_SHARED,
|
| 96 | .header.len = sizeof(uvcb),
|
| 97 | .paddr = paddr,
|
| 98 | };
|
| 99 |
|
| 100 | if (uv_call(0, (u64)&uvcb))
|
| 101 | return -EINVAL;
|
| 102 | return 0;
|
| 103 | }
|
| 104 | EXPORT_SYMBOL_GPL(uv_pin_shared);
|
| 105 |
|
| 106 | |
| 107 | * Requests the Ultravisor to destroy a guest page and make it
|
| 108 | * accessible to the host. The destroy clears the page instead of
|
| 109 | * exporting.
|
| 110 | *
|
| 111 | * @paddr: Absolute host address of page to be destroyed
|
| 112 |
|
| 113 | static int uv_destroy(unsigned long paddr)
|
| 114 | {
|
| 115 | struct uv_cb_cfs uvcb = {
|
| 116 | .header.cmd = UVC_CMD_DESTR_SEC_STOR,
|
| 117 | .header.len = sizeof(uvcb),
|
| 118 | .paddr = paddr
|
| 119 | };
|
| 120 |
|
| 121 | if (uv_call(0, (u64)&uvcb)) {
|
| 122 | |
| 123 | * Older firmware uses 107/d as an indication of a non secure
|
| 124 | * page. Let us emulate the newer variant (no-op).
|
| 125 |
|
| 126 | if (uvcb.header.rc == 0x107 && uvcb.header.rrc == 0xd)
|
| 127 | return 0;
|
| 128 | return -EINVAL;
|
| 129 | }
|
| 130 | return 0;
|
| 131 | }
|
| 132 |
|
| 133 | |
| 134 | * The caller must already hold a reference to the folio
|
| 135 |
|
| 136 | int uv_destroy_folio(struct folio *folio)
|
| 137 | {
|
| 138 | unsigned long i;
|
| 139 | int rc;
|
| 140 |
|
| 141 | folio_get(folio);
|
| 142 | for (i = 0; i < (1 << folio_order(folio)); i++) {
|
| 143 | rc = uv_destroy(folio_to_phys(folio) + i * PAGE_SIZE);
|
| 144 | if (rc)
|
| 145 | break;
|
| 146 | }
|
| 147 | if (!rc)
|
| 148 | clear_bit(PG_arch_1, &folio->flags.f);
|
| 149 | folio_put(folio);
|
| 150 | return rc;
|
| 151 | }
|
| 152 | EXPORT_SYMBOL(uv_destroy_folio);
|
| 153 |
|
| 154 | |
| 155 | * The present PTE still indirectly holds a folio reference through the mapping.
|
| 156 |
|
| 157 | int uv_destroy_pte(pte_t pte)
|
| 158 | {
|
| 159 | VM_WARN_ON(!pte_present(pte));
|
| 160 | return uv_destroy_folio(pfn_folio(pte_pfn(pte)));
|
| 161 | }
|
| 162 |
|
| 163 | |
| 164 | * Requests the Ultravisor to encrypt a guest page and make it
|
| 165 | * accessible to the host for paging (export).
|
| 166 | *
|
| 167 | * @paddr: Absolute host address of page to be exported
|
| 168 |
|
| 169 | int uv_convert_from_secure(unsigned long paddr)
|
| 170 | {
|
| 171 | struct uv_cb_cfs uvcb = {
|
| 172 | .header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
|
| 173 | .header.len = sizeof(uvcb),
|
| 174 | .paddr = paddr
|
| 175 | };
|
| 176 |
|
| 177 | if (uv_call(0, (u64)&uvcb))
|
| 178 | return -EINVAL;
|
| 179 | return 0;
|
| 180 | }
|
| 181 | EXPORT_SYMBOL_GPL(uv_convert_from_secure);
|
| 182 |
|
| 183 | |
| 184 | * The caller must already hold a reference to the folio.
|
| 185 |
|
| 186 | int uv_convert_from_secure_folio(struct folio *folio)
|
| 187 | {
|
| 188 | unsigned long i;
|
| 189 | int rc;
|
| 190 |
|
| 191 | folio_get(folio);
|
| 192 | for (i = 0; i < (1 << folio_order(folio)); i++) {
|
| 193 | rc = uv_convert_from_secure(folio_to_phys(folio) + i * PAGE_SIZE);
|
| 194 | if (rc)
|
| 195 | break;
|
| 196 | }
|
| 197 | if (!rc)
|
| 198 | clear_bit(PG_arch_1, &folio->flags.f);
|
| 199 | folio_put(folio);
|
| 200 | return rc;
|
| 201 | }
|
| 202 | EXPORT_SYMBOL_GPL(uv_convert_from_secure_folio);
|
| 203 |
|
| 204 | |
| 205 | * The present PTE still indirectly holds a folio reference through the mapping.
|
| 206 |
|
| 207 | int uv_convert_from_secure_pte(pte_t pte)
|
| 208 | {
|
| 209 | VM_WARN_ON(!pte_present(pte));
|
| 210 | return uv_convert_from_secure_folio(pfn_folio(pte_pfn(pte)));
|
| 211 | }
|
| 212 |
|
| 213 | static int uv_free_range_cb(pte_t *ptep, unsigned long addr, void *data)
|
| 214 | {
|
| 215 | pte_t pte = ptep_get(ptep);
|
| 216 |
|
| 217 | if (!pte_present(pte))
|
| 218 | return 0;
|
| 219 | |
| 220 | * Note: do not update the pte here, since there is no code which
|
| 221 | * accesses the memory range, besides bugs. The invalidation of ptes
|
| 222 | * and TLB flushing is deferred like for regular vfree() calls.
|
| 223 |
|
| 224 | __free_page(pte_page(pte));
|
| 225 | return 0;
|
| 226 | }
|
| 227 |
|
| 228 | void uv_free_stor_var(void *stor_var)
|
| 229 | {
|
| 230 | unsigned long addr, size;
|
| 231 | struct vm_struct *area;
|
| 232 |
|
| 233 | if (!stor_var)
|
| 234 | return;
|
| 235 | area = find_vm_area(stor_var);
|
| 236 | if (WARN_ON_ONCE(!area || !(area->flags & VM_SPARSE)))
|
| 237 | return;
|
| 238 | size = get_vm_area_size(area);
|
| 239 | addr = (unsigned long)area->addr;
|
| 240 | apply_to_existing_page_range(&init_mm, addr, size, uv_free_range_cb, NULL);
|
| 241 | free_vm_area(area);
|
| 242 | }
|
| 243 | EXPORT_SYMBOL_FOR_MODULES(uv_free_stor_var, "kvm");
|
| 244 |
|
| 245 | static int uv_alloc_range_cb(pte_t *ptep, unsigned long addr, void *data)
|
| 246 | {
|
| 247 | struct page *page;
|
| 248 | pte_t pte;
|
| 249 |
|
| 250 | page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
|
| 251 | if (!page)
|
| 252 | return -ENOMEM;
|
| 253 | pte = __pte(page_to_phys(page) | pgprot_val(PAGE_KERNEL));
|
| 254 | set_pte(ptep, pte);
|
| 255 | return 0;
|
| 256 | }
|
| 257 |
|
| 258 | void *uv_alloc_stor_var(unsigned long size)
|
| 259 | {
|
| 260 | struct vm_struct *area;
|
| 261 | unsigned long addr;
|
| 262 |
|
| 263 | size = PAGE_ALIGN(size);
|
| 264 | area = get_vm_area(size, VM_SPARSE);
|
| 265 | if (!area)
|
| 266 | return NULL;
|
| 267 | addr = (unsigned long)area->addr;
|
| 268 | if (apply_to_page_range(&init_mm, addr, size, uv_alloc_range_cb, NULL))
|
| 269 | goto out;
|
| 270 | return area->addr;
|
| 271 | out:
|
| 272 | uv_free_stor_var(area->addr);
|
| 273 | return NULL;
|
| 274 | }
|
| 275 | EXPORT_SYMBOL_FOR_MODULES(uv_alloc_stor_var, "kvm");
|
| 276 |
|
| 277 | |
| 278 | * Calculate the expected ref_count for a folio that would otherwise have no
|
| 279 | * further pins. This was cribbed from similar functions in other places in
|
| 280 | * the kernel, but with some slight modifications. We know that a secure
|
| 281 | * folio can not be a large folio, for example.
|
| 282 |
|
| 283 | static int expected_folio_refs(struct folio *folio)
|
| 284 | {
|
| 285 | int res;
|
| 286 |
|
| 287 | res = folio_mapcount(folio);
|
| 288 | if (folio_test_swapcache(folio)) {
|
| 289 | res++;
|
| 290 | } else if (folio_mapping(folio)) {
|
| 291 | res++;
|
| 292 | if (folio->private)
|
| 293 | res++;
|
| 294 | }
|
| 295 | return res;
|
| 296 | }
|
| 297 |
|
| 298 | |
| 299 | * __make_folio_secure() - make a folio secure
|
| 300 | * @folio: the folio to make secure
|
| 301 | * @uvcb: the uvcb that describes the UVC to be used
|
| 302 | *
|
| 303 | * The folio @folio will be made secure if possible, @uvcb will be passed
|
| 304 | * as-is to the UVC.
|
| 305 | *
|
| 306 | * Return: 0 on success;
|
| 307 | * -EBUSY if the folio is in writeback or has too many references;
|
| 308 | * -EAGAIN if the UVC needs to be attempted again;
|
| 309 | * -ENXIO if the address is not mapped;
|
| 310 | * -EINVAL if the UVC failed for other reasons.
|
| 311 | *
|
| 312 | * Context: The caller must hold exactly one extra reference on the folio
|
| 313 | * (it's the same logic as split_folio()), and the folio must be
|
| 314 | * locked.
|
| 315 |
|
| 316 | int __make_folio_secure(struct folio *folio, struct uv_cb_header *uvcb)
|
| 317 | {
|
| 318 | int expected, cc = 0;
|
| 319 |
|
| 320 | if (folio_test_writeback(folio))
|
| 321 | return -EBUSY;
|
| 322 | expected = expected_folio_refs(folio) + 1;
|
| 323 | if (!folio_ref_freeze(folio, expected))
|
| 324 | return -EBUSY;
|
| 325 | set_bit(PG_arch_1, &folio->flags.f);
|
| 326 | |
| 327 | * If the UVC does not succeed or fail immediately, we don't want to
|
| 328 | * loop for long, or we might get stall notifications.
|
| 329 | * On the other hand, this is a complex scenario and we are holding a lot of
|
| 330 | * locks, so we can't easily sleep and reschedule. We try only once,
|
| 331 | * and if the UVC returned busy or partial completion, we return
|
| 332 | * -EAGAIN and we let the callers deal with it.
|
| 333 |
|
| 334 | cc = __uv_call(0, (u64)uvcb);
|
| 335 | folio_ref_unfreeze(folio, expected);
|
| 336 | |
| 337 | * Return -ENXIO if the folio was not mapped, -EINVAL for other errors.
|
| 338 | * If busy or partially completed, return -EAGAIN.
|
| 339 |
|
| 340 | if (cc == UVC_CC_OK)
|
| 341 | return 0;
|
| 342 | else if (cc == UVC_CC_BUSY || cc == UVC_CC_PARTIAL)
|
| 343 | return -EAGAIN;
|
| 344 | return uvcb->rc == 0x10a ? -ENXIO : -EINVAL;
|
| 345 | }
|
| 346 | EXPORT_SYMBOL(__make_folio_secure);
|
| 347 |
|
| 348 | |
| 349 | * s390_wiggle_split_folio() - try to drain extra references to a folio and
|
| 350 | * split the folio if it is large.
|
| 351 | * @mm: the mm containing the folio to work on
|
| 352 | * @folio: the folio
|
| 353 | *
|
| 354 | * Context: Must be called while holding an extra reference to the folio;
|
| 355 | * the mm lock should not be held.
|
| 356 | * Return: 0 if the operation was successful;
|
| 357 | * -EAGAIN if splitting the large folio was not successful,
|
| 358 | * but another attempt can be made;
|
| 359 | * -EINVAL in case of other folio splitting errors. See split_folio().
|
| 360 |
|
| 361 | int s390_wiggle_split_folio(struct mm_struct *mm, struct folio *folio)
|
| 362 | {
|
| 363 | int rc, tried_splits;
|
| 364 |
|
| 365 | lockdep_assert_not_held(&mm->mmap_lock);
|
| 366 | folio_wait_writeback(folio);
|
| 367 | lru_add_drain_all();
|
| 368 |
|
| 369 | if (!folio_test_large(folio))
|
| 370 | return 0;
|
| 371 |
|
| 372 | for (tried_splits = 0; tried_splits < 2; tried_splits++) {
|
| 373 | struct address_space *mapping;
|
| 374 | loff_t lstart, lend;
|
| 375 | struct inode *inode;
|
| 376 |
|
| 377 | folio_lock(folio);
|
| 378 | rc = split_folio(folio);
|
| 379 | if (rc != -EBUSY) {
|
| 380 | folio_unlock(folio);
|
| 381 | return rc;
|
| 382 | }
|
| 383 |
|
| 384 | |
| 385 | * Splitting with -EBUSY can fail for various reasons, but we
|
| 386 | * have to handle one case explicitly for now: some mappings
|
| 387 | * don't allow for splitting dirty folios; writeback will
|
| 388 | * mark them clean again, including marking all page table
|
| 389 | * entries mapping the folio read-only, to catch future write
|
| 390 | * attempts.
|
| 391 | *
|
| 392 | * While the system should be writing back dirty folios in the
|
| 393 | * background, we obtained this folio by looking up a writable
|
| 394 | * page table entry. On these problematic mappings, writable
|
| 395 | * page table entries imply dirty folios, preventing the
|
| 396 | * split in the first place.
|
| 397 | *
|
| 398 | * To prevent a livelock when trigger writeback manually and
|
| 399 | * letting the caller look up the folio again in the page
|
| 400 | * table (turning it dirty), immediately try to split again.
|
| 401 | *
|
| 402 | * This is only a problem for some mappings (e.g., XFS);
|
| 403 | * mappings that do not support writeback (e.g., shmem) do not
|
| 404 | * apply.
|
| 405 |
|
| 406 | if (!folio_test_dirty(folio) || folio_test_anon(folio) ||
|
| 407 | !folio->mapping || !mapping_can_writeback(folio->mapping)) {
|
| 408 | folio_unlock(folio);
|
| 409 | break;
|
| 410 | }
|
| 411 |
|
| 412 | |
| 413 | * Ideally, we'd only trigger writeback on this exact folio. But
|
| 414 | * there is no easy way to do that, so we'll stabilize the
|
| 415 | * mapping while we still hold the folio lock, so we can drop
|
| 416 | * the folio lock to trigger writeback on the range currently
|
| 417 | * covered by the folio instead.
|
| 418 |
|
| 419 | mapping = folio->mapping;
|
| 420 | lstart = folio_pos(folio);
|
| 421 | lend = lstart + folio_size(folio) - 1;
|
| 422 | inode = igrab(mapping->host);
|
| 423 | folio_unlock(folio);
|
| 424 |
|
| 425 | if (unlikely(!inode))
|
| 426 | break;
|
| 427 |
|
| 428 | filemap_write_and_wait_range(mapping, lstart, lend);
|
| 429 | iput(mapping->host);
|
| 430 | }
|
| 431 | return -EAGAIN;
|
| 432 | }
|
| 433 | EXPORT_SYMBOL_GPL(s390_wiggle_split_folio);
|
| 434 |
|
| 435 | |
| 436 | * To be called with the folio locked or with an extra reference! This will
|
| 437 | * prevent kvm_s390_pv_make_secure() from touching the folio concurrently.
|
| 438 | * Having 2 parallel arch_make_folio_accessible is fine, as the UV calls will
|
| 439 | * become a no-op if the folio is already exported.
|
| 440 |
|
| 441 | int arch_make_folio_accessible(struct folio *folio)
|
| 442 | {
|
| 443 | int rc = 0;
|
| 444 |
|
| 445 | |
| 446 | * PG_arch_1 is used as an indication that this small folio might be
|
| 447 | * secure. This can overindicate, e.g. we set the bit before calling
|
| 448 | * convert_to_secure.
|
| 449 |
|
| 450 | if (!test_bit(PG_arch_1, &folio->flags.f))
|
| 451 | return 0;
|
| 452 |
|
| 453 |
|
| 454 | if (WARN_ON_ONCE(folio_test_large(folio)))
|
| 455 | return -EFAULT;
|
| 456 |
|
| 457 | rc = uv_pin_shared(folio_to_phys(folio));
|
| 458 | if (!rc) {
|
| 459 | clear_bit(PG_arch_1, &folio->flags.f);
|
| 460 | return 0;
|
| 461 | }
|
| 462 |
|
| 463 | rc = uv_convert_from_secure(folio_to_phys(folio));
|
| 464 | if (!rc) {
|
| 465 | clear_bit(PG_arch_1, &folio->flags.f);
|
| 466 | return 0;
|
| 467 | }
|
| 468 |
|
| 469 | return rc;
|
| 470 | }
|
| 471 | EXPORT_SYMBOL_GPL(arch_make_folio_accessible);
|
| 472 |
|
| 473 | static ssize_t uv_query_facilities(struct kobject *kobj,
|
| 474 | struct kobj_attribute *attr, char *buf)
|
| 475 | {
|
| 476 | return sysfs_emit(buf, "%lx\n%lx\n%lx\n%lx\n",
|
| 477 | uv_info.inst_calls_list[0],
|
| 478 | uv_info.inst_calls_list[1],
|
| 479 | uv_info.inst_calls_list[2],
|
| 480 | uv_info.inst_calls_list[3]);
|
| 481 | }
|
| 482 |
|
| 483 | static struct kobj_attribute uv_query_facilities_attr =
|
| 484 | __ATTR(facilities, 0444, uv_query_facilities, NULL);
|
| 485 |
|
| 486 | static ssize_t uv_query_supp_se_hdr_ver(struct kobject *kobj,
|
| 487 | struct kobj_attribute *attr, char *buf)
|
| 488 | {
|
| 489 | return sysfs_emit(buf, "%lx\n", uv_info.supp_se_hdr_ver);
|
| 490 | }
|
| 491 |
|
| 492 | static struct kobj_attribute uv_query_supp_se_hdr_ver_attr =
|
| 493 | __ATTR(supp_se_hdr_ver, 0444, uv_query_supp_se_hdr_ver, NULL);
|
| 494 |
|
| 495 | static ssize_t uv_query_supp_se_hdr_pcf(struct kobject *kobj,
|
| 496 | struct kobj_attribute *attr, char *buf)
|
| 497 | {
|
| 498 | return sysfs_emit(buf, "%lx\n", uv_info.supp_se_hdr_pcf);
|
| 499 | }
|
| 500 |
|
| 501 | static struct kobj_attribute uv_query_supp_se_hdr_pcf_attr =
|
| 502 | __ATTR(supp_se_hdr_pcf, 0444, uv_query_supp_se_hdr_pcf, NULL);
|
| 503 |
|
| 504 | static ssize_t uv_query_dump_cpu_len(struct kobject *kobj,
|
| 505 | struct kobj_attribute *attr, char *buf)
|
| 506 | {
|
| 507 | return sysfs_emit(buf, "%lx\n", uv_info.guest_cpu_stor_len);
|
| 508 | }
|
| 509 |
|
| 510 | static struct kobj_attribute uv_query_dump_cpu_len_attr =
|
| 511 | __ATTR(uv_query_dump_cpu_len, 0444, uv_query_dump_cpu_len, NULL);
|
| 512 |
|
| 513 | static ssize_t uv_query_dump_storage_state_len(struct kobject *kobj,
|
| 514 | struct kobj_attribute *attr, char *buf)
|
| 515 | {
|
| 516 | return sysfs_emit(buf, "%lx\n", uv_info.conf_dump_storage_state_len);
|
| 517 | }
|
| 518 |
|
| 519 | static struct kobj_attribute uv_query_dump_storage_state_len_attr =
|
| 520 | __ATTR(dump_storage_state_len, 0444, uv_query_dump_storage_state_len, NULL);
|
| 521 |
|
| 522 | static ssize_t uv_query_dump_finalize_len(struct kobject *kobj,
|
| 523 | struct kobj_attribute *attr, char *buf)
|
| 524 | {
|
| 525 | return sysfs_emit(buf, "%lx\n", uv_info.conf_dump_finalize_len);
|
| 526 | }
|
| 527 |
|
| 528 | static struct kobj_attribute uv_query_dump_finalize_len_attr =
|
| 529 | __ATTR(dump_finalize_len, 0444, uv_query_dump_finalize_len, NULL);
|
| 530 |
|
| 531 | static ssize_t uv_query_feature_indications(struct kobject *kobj,
|
| 532 | struct kobj_attribute *attr, char *buf)
|
| 533 | {
|
| 534 | return sysfs_emit(buf, "%lx\n", uv_info.uv_feature_indications);
|
| 535 | }
|
| 536 |
|
| 537 | static struct kobj_attribute uv_query_feature_indications_attr =
|
| 538 | __ATTR(feature_indications, 0444, uv_query_feature_indications, NULL);
|
| 539 |
|
| 540 | static ssize_t uv_query_max_guest_cpus(struct kobject *kobj,
|
| 541 | struct kobj_attribute *attr, char *buf)
|
| 542 | {
|
| 543 | return sysfs_emit(buf, "%d\n", uv_info.max_guest_cpu_id + 1);
|
| 544 | }
|
| 545 |
|
| 546 | static struct kobj_attribute uv_query_max_guest_cpus_attr =
|
| 547 | __ATTR(max_cpus, 0444, uv_query_max_guest_cpus, NULL);
|
| 548 |
|
| 549 | static ssize_t uv_query_max_guest_vms(struct kobject *kobj,
|
| 550 | struct kobj_attribute *attr, char *buf)
|
| 551 | {
|
| 552 | return sysfs_emit(buf, "%d\n", uv_info.max_num_sec_conf);
|
| 553 | }
|
| 554 |
|
| 555 | static struct kobj_attribute uv_query_max_guest_vms_attr =
|
| 556 | __ATTR(max_guests, 0444, uv_query_max_guest_vms, NULL);
|
| 557 |
|
| 558 | static ssize_t uv_query_max_guest_addr(struct kobject *kobj,
|
| 559 | struct kobj_attribute *attr, char *buf)
|
| 560 | {
|
| 561 | return sysfs_emit(buf, "%lx\n", uv_info.max_sec_stor_addr);
|
| 562 | }
|
| 563 |
|
| 564 | static struct kobj_attribute uv_query_max_guest_addr_attr =
|
| 565 | __ATTR(max_address, 0444, uv_query_max_guest_addr, NULL);
|
| 566 |
|
| 567 | static ssize_t uv_query_supp_att_req_hdr_ver(struct kobject *kobj,
|
| 568 | struct kobj_attribute *attr, char *buf)
|
| 569 | {
|
| 570 | return sysfs_emit(buf, "%lx\n", uv_info.supp_att_req_hdr_ver);
|
| 571 | }
|
| 572 |
|
| 573 | static struct kobj_attribute uv_query_supp_att_req_hdr_ver_attr =
|
| 574 | __ATTR(supp_att_req_hdr_ver, 0444, uv_query_supp_att_req_hdr_ver, NULL);
|
| 575 |
|
| 576 | static ssize_t uv_query_supp_att_pflags(struct kobject *kobj,
|
| 577 | struct kobj_attribute *attr, char *buf)
|
| 578 | {
|
| 579 | return sysfs_emit(buf, "%lx\n", uv_info.supp_att_pflags);
|
| 580 | }
|
| 581 |
|
| 582 | static struct kobj_attribute uv_query_supp_att_pflags_attr =
|
| 583 | __ATTR(supp_att_pflags, 0444, uv_query_supp_att_pflags, NULL);
|
| 584 |
|
| 585 | static ssize_t uv_query_supp_add_secret_req_ver(struct kobject *kobj,
|
| 586 | struct kobj_attribute *attr, char *buf)
|
| 587 | {
|
| 588 | return sysfs_emit(buf, "%lx\n", uv_info.supp_add_secret_req_ver);
|
| 589 | }
|
| 590 |
|
| 591 | static struct kobj_attribute uv_query_supp_add_secret_req_ver_attr =
|
| 592 | __ATTR(supp_add_secret_req_ver, 0444, uv_query_supp_add_secret_req_ver, NULL);
|
| 593 |
|
| 594 | static ssize_t uv_query_supp_add_secret_pcf(struct kobject *kobj,
|
| 595 | struct kobj_attribute *attr, char *buf)
|
| 596 | {
|
| 597 | return sysfs_emit(buf, "%lx\n", uv_info.supp_add_secret_pcf);
|
| 598 | }
|
| 599 |
|
| 600 | static struct kobj_attribute uv_query_supp_add_secret_pcf_attr =
|
| 601 | __ATTR(supp_add_secret_pcf, 0444, uv_query_supp_add_secret_pcf, NULL);
|
| 602 |
|
| 603 | static ssize_t uv_query_supp_secret_types(struct kobject *kobj,
|
| 604 | struct kobj_attribute *attr, char *buf)
|
| 605 | {
|
| 606 | return sysfs_emit(buf, "%lx\n", uv_info.supp_secret_types);
|
| 607 | }
|
| 608 |
|
| 609 | static struct kobj_attribute uv_query_supp_secret_types_attr =
|
| 610 | __ATTR(supp_secret_types, 0444, uv_query_supp_secret_types, NULL);
|
| 611 |
|
| 612 | static ssize_t uv_query_max_secrets(struct kobject *kobj,
|
| 613 | struct kobj_attribute *attr, char *buf)
|
| 614 | {
|
| 615 | return sysfs_emit(buf, "%d\n",
|
| 616 | uv_info.max_assoc_secrets + uv_info.max_retr_secrets);
|
| 617 | }
|
| 618 |
|
| 619 | static struct kobj_attribute uv_query_max_secrets_attr =
|
| 620 | __ATTR(max_secrets, 0444, uv_query_max_secrets, NULL);
|
| 621 |
|
| 622 | static ssize_t uv_query_max_retr_secrets(struct kobject *kobj,
|
| 623 | struct kobj_attribute *attr, char *buf)
|
| 624 | {
|
| 625 | return sysfs_emit(buf, "%d\n", uv_info.max_retr_secrets);
|
| 626 | }
|
| 627 |
|
| 628 | static struct kobj_attribute uv_query_max_retr_secrets_attr =
|
| 629 | __ATTR(max_retr_secrets, 0444, uv_query_max_retr_secrets, NULL);
|
| 630 |
|
| 631 | static ssize_t uv_query_max_assoc_secrets(struct kobject *kobj,
|
| 632 | struct kobj_attribute *attr,
|
| 633 | char *buf)
|
| 634 | {
|
| 635 | return sysfs_emit(buf, "%d\n", uv_info.max_assoc_secrets);
|
| 636 | }
|
| 637 |
|
| 638 | static struct kobj_attribute uv_query_max_assoc_secrets_attr =
|
| 639 | __ATTR(max_assoc_secrets, 0444, uv_query_max_assoc_secrets, NULL);
|
| 640 |
|
| 641 | static struct attribute *uv_query_attrs[] = {
|
| 642 | &uv_query_facilities_attr.attr,
|
| 643 | &uv_query_feature_indications_attr.attr,
|
| 644 | &uv_query_max_guest_cpus_attr.attr,
|
| 645 | &uv_query_max_guest_vms_attr.attr,
|
| 646 | &uv_query_max_guest_addr_attr.attr,
|
| 647 | &uv_query_supp_se_hdr_ver_attr.attr,
|
| 648 | &uv_query_supp_se_hdr_pcf_attr.attr,
|
| 649 | &uv_query_dump_storage_state_len_attr.attr,
|
| 650 | &uv_query_dump_finalize_len_attr.attr,
|
| 651 | &uv_query_dump_cpu_len_attr.attr,
|
| 652 | &uv_query_supp_att_req_hdr_ver_attr.attr,
|
| 653 | &uv_query_supp_att_pflags_attr.attr,
|
| 654 | &uv_query_supp_add_secret_req_ver_attr.attr,
|
| 655 | &uv_query_supp_add_secret_pcf_attr.attr,
|
| 656 | &uv_query_supp_secret_types_attr.attr,
|
| 657 | &uv_query_max_secrets_attr.attr,
|
| 658 | &uv_query_max_assoc_secrets_attr.attr,
|
| 659 | &uv_query_max_retr_secrets_attr.attr,
|
| 660 | NULL,
|
| 661 | };
|
| 662 |
|
| 663 | static inline struct uv_cb_query_keys uv_query_keys(void)
|
| 664 | {
|
| 665 | struct uv_cb_query_keys uvcb = {
|
| 666 | .header.cmd = UVC_CMD_QUERY_KEYS,
|
| 667 | .header.len = sizeof(uvcb)
|
| 668 | };
|
| 669 |
|
| 670 | uv_call(0, (uint64_t)&uvcb);
|
| 671 | return uvcb;
|
| 672 | }
|
| 673 |
|
| 674 | static inline ssize_t emit_hash(struct uv_key_hash *hash, char *buf, int at)
|
| 675 | {
|
| 676 | return sysfs_emit_at(buf, at, "%016llx%016llx%016llx%016llx\n",
|
| 677 | hash->dword[0], hash->dword[1], hash->dword[2], hash->dword[3]);
|
| 678 | }
|
| 679 |
|
| 680 | static ssize_t uv_keys_host_key(struct kobject *kobj,
|
| 681 | struct kobj_attribute *attr, char *buf)
|
| 682 | {
|
| 683 | struct uv_cb_query_keys uvcb = uv_query_keys();
|
| 684 |
|
| 685 | return emit_hash(&uvcb.key_hashes[UVC_QUERY_KEYS_IDX_HK], buf, 0);
|
| 686 | }
|
| 687 |
|
| 688 | static struct kobj_attribute uv_keys_host_key_attr =
|
| 689 | __ATTR(host_key, 0444, uv_keys_host_key, NULL);
|
| 690 |
|
| 691 | static ssize_t uv_keys_backup_host_key(struct kobject *kobj,
|
| 692 | struct kobj_attribute *attr, char *buf)
|
| 693 | {
|
| 694 | struct uv_cb_query_keys uvcb = uv_query_keys();
|
| 695 |
|
| 696 | return emit_hash(&uvcb.key_hashes[UVC_QUERY_KEYS_IDX_BACK_HK], buf, 0);
|
| 697 | }
|
| 698 |
|
| 699 | static struct kobj_attribute uv_keys_backup_host_key_attr =
|
| 700 | __ATTR(backup_host_key, 0444, uv_keys_backup_host_key, NULL);
|
| 701 |
|
| 702 | static ssize_t uv_keys_all(struct kobject *kobj,
|
| 703 | struct kobj_attribute *attr, char *buf)
|
| 704 | {
|
| 705 | struct uv_cb_query_keys uvcb = uv_query_keys();
|
| 706 | ssize_t len = 0;
|
| 707 | int i;
|
| 708 |
|
| 709 | for (i = 0; i < ARRAY_SIZE(uvcb.key_hashes); i++)
|
| 710 | len += emit_hash(uvcb.key_hashes + i, buf, len);
|
| 711 |
|
| 712 | return len;
|
| 713 | }
|
| 714 |
|
| 715 | static struct kobj_attribute uv_keys_all_attr =
|
| 716 | __ATTR(all, 0444, uv_keys_all, NULL);
|
| 717 |
|
| 718 | static struct attribute_group uv_query_attr_group = {
|
| 719 | .attrs = uv_query_attrs,
|
| 720 | };
|
| 721 |
|
| 722 | static struct attribute *uv_keys_attrs[] = {
|
| 723 | &uv_keys_host_key_attr.attr,
|
| 724 | &uv_keys_backup_host_key_attr.attr,
|
| 725 | &uv_keys_all_attr.attr,
|
| 726 | NULL,
|
| 727 | };
|
| 728 |
|
| 729 | static struct attribute_group uv_keys_attr_group = {
|
| 730 | .attrs = uv_keys_attrs,
|
| 731 | };
|
| 732 |
|
| 733 | static ssize_t uv_is_prot_virt_guest(struct kobject *kobj,
|
| 734 | struct kobj_attribute *attr, char *buf)
|
| 735 | {
|
| 736 | return sysfs_emit(buf, "%d\n", prot_virt_guest);
|
| 737 | }
|
| 738 |
|
| 739 | static ssize_t uv_is_prot_virt_host(struct kobject *kobj,
|
| 740 | struct kobj_attribute *attr, char *buf)
|
| 741 | {
|
| 742 | return sysfs_emit(buf, "%d\n", prot_virt_host);
|
| 743 | }
|
| 744 |
|
| 745 | static struct kobj_attribute uv_prot_virt_guest =
|
| 746 | __ATTR(prot_virt_guest, 0444, uv_is_prot_virt_guest, NULL);
|
| 747 |
|
| 748 | static struct kobj_attribute uv_prot_virt_host =
|
| 749 | __ATTR(prot_virt_host, 0444, uv_is_prot_virt_host, NULL);
|
| 750 |
|
| 751 | static const struct attribute *uv_prot_virt_attrs[] = {
|
| 752 | &uv_prot_virt_guest.attr,
|
| 753 | &uv_prot_virt_host.attr,
|
| 754 | NULL,
|
| 755 | };
|
| 756 |
|
| 757 | static struct kset *uv_query_kset;
|
| 758 | static struct kset *uv_keys_kset;
|
| 759 | static struct kobject *uv_kobj;
|
| 760 |
|
| 761 | static int __init uv_sysfs_dir_init(const struct attribute_group *grp,
|
| 762 | struct kset **uv_dir_kset, const char *name)
|
| 763 | {
|
| 764 | struct kset *kset;
|
| 765 | int rc;
|
| 766 |
|
| 767 | kset = kset_create_and_add(name, NULL, uv_kobj);
|
| 768 | if (!kset)
|
| 769 | return -ENOMEM;
|
| 770 | *uv_dir_kset = kset;
|
| 771 |
|
| 772 | rc = sysfs_create_group(&kset->kobj, grp);
|
| 773 | if (rc)
|
| 774 | kset_unregister(kset);
|
| 775 | return rc;
|
| 776 | }
|
| 777 |
|
| 778 | static int __init uv_sysfs_init(void)
|
| 779 | {
|
| 780 | int rc = -ENOMEM;
|
| 781 |
|
| 782 | if (!test_facility(158))
|
| 783 | return 0;
|
| 784 |
|
| 785 | uv_kobj = kobject_create_and_add("uv", firmware_kobj);
|
| 786 | if (!uv_kobj)
|
| 787 | return -ENOMEM;
|
| 788 |
|
| 789 | rc = sysfs_create_files(uv_kobj, uv_prot_virt_attrs);
|
| 790 | if (rc)
|
| 791 | goto out_kobj;
|
| 792 |
|
| 793 | rc = uv_sysfs_dir_init(&uv_query_attr_group, &uv_query_kset, "query");
|
| 794 | if (rc)
|
| 795 | goto out_ind_files;
|
| 796 |
|
| 797 |
|
| 798 | if (test_bit_inv(BIT_UVC_CMD_QUERY_KEYS, uv_info.inst_calls_list))
|
| 799 | uv_sysfs_dir_init(&uv_keys_attr_group, &uv_keys_kset, "keys");
|
| 800 |
|
| 801 | return 0;
|
| 802 |
|
| 803 | out_ind_files:
|
| 804 | sysfs_remove_files(uv_kobj, uv_prot_virt_attrs);
|
| 805 | out_kobj:
|
| 806 | kobject_del(uv_kobj);
|
| 807 | kobject_put(uv_kobj);
|
| 808 | return rc;
|
| 809 | }
|
| 810 | device_initcall(uv_sysfs_init);
|
| 811 |
|
| 812 | |
| 813 | * Locate a secret in the list by its id.
|
| 814 | * @secret_id: search pattern.
|
| 815 | * @list: ephemeral buffer space
|
| 816 | * @secret: output data, containing the secret's metadata.
|
| 817 | *
|
| 818 | * Search for a secret with the given secret_id in the Ultravisor secret store.
|
| 819 | *
|
| 820 | * Context: might sleep.
|
| 821 |
|
| 822 | static int find_secret_in_page(const u8 secret_id[UV_SECRET_ID_LEN],
|
| 823 | const struct uv_secret_list *list,
|
| 824 | struct uv_secret_list_item_hdr *secret)
|
| 825 | {
|
| 826 | u16 i;
|
| 827 |
|
| 828 | for (i = 0; i < list->num_secr_stored; i++) {
|
| 829 | if (memcmp(secret_id, list->secrets[i].id, UV_SECRET_ID_LEN) == 0) {
|
| 830 | *secret = list->secrets[i].hdr;
|
| 831 | return 0;
|
| 832 | }
|
| 833 | }
|
| 834 | return -ENOENT;
|
| 835 | }
|
| 836 |
|
| 837 | |
| 838 | * uv_find_secret() - search secret metadata for a given secret id.
|
| 839 | * @secret_id: search pattern.
|
| 840 | * @list: ephemeral buffer space
|
| 841 | * @secret: output data, containing the secret's metadata.
|
| 842 | *
|
| 843 | * Context: might sleep.
|
| 844 |
|
| 845 | int uv_find_secret(const u8 secret_id[UV_SECRET_ID_LEN],
|
| 846 | struct uv_secret_list *list,
|
| 847 | struct uv_secret_list_item_hdr *secret)
|
| 848 | {
|
| 849 | u16 start_idx;
|
| 850 | u16 list_rc;
|
| 851 | int ret;
|
| 852 |
|
| 853 | list->next_secret_idx = 0;
|
| 854 |
|
| 855 | do {
|
| 856 | start_idx = list->next_secret_idx;
|
| 857 | uv_list_secrets(list, start_idx, &list_rc, NULL);
|
| 858 | if (list_rc != UVC_RC_EXECUTED && list_rc != UVC_RC_MORE_DATA) {
|
| 859 | if (list_rc == UVC_RC_INV_CMD)
|
| 860 | return -ENODEV;
|
| 861 | else
|
| 862 | return -EIO;
|
| 863 | }
|
| 864 | ret = find_secret_in_page(secret_id, list, secret);
|
| 865 | if (ret == 0)
|
| 866 | return ret;
|
| 867 | } while (list_rc == UVC_RC_MORE_DATA && start_idx < list->next_secret_idx);
|
| 868 |
|
| 869 | return -ENOENT;
|
| 870 | }
|
| 871 | EXPORT_SYMBOL_GPL(uv_find_secret);
|
| 872 |
|
| 873 | |
| 874 | * uv_retrieve_secret() - get the secret value for the secret index.
|
| 875 | * @secret_idx: Secret index for which the secret should be retrieved.
|
| 876 | * @buf: Buffer to store retrieved secret.
|
| 877 | * @buf_size: Size of the buffer. The correct buffer size is reported as part of
|
| 878 | * the result from `uv_get_secret_metadata`.
|
| 879 | *
|
| 880 | * Calls the Retrieve Secret UVC and translates the UV return code into an errno.
|
| 881 | *
|
| 882 | * Context: might sleep.
|
| 883 | *
|
| 884 | * Return:
|
| 885 | * * %0 - Entry found; buffer contains a valid secret.
|
| 886 | * * %ENOENT: - No entry found or secret at the index is non-retrievable.
|
| 887 | * * %ENODEV: - Not supported: UV not available or command not available.
|
| 888 | * * %EINVAL: - Buffer too small for content.
|
| 889 | * * %EIO: - Other unexpected UV error.
|
| 890 |
|
| 891 | int uv_retrieve_secret(u16 secret_idx, u8 *buf, size_t buf_size)
|
| 892 | {
|
| 893 | struct uv_cb_retr_secr uvcb = {
|
| 894 | .header.len = sizeof(uvcb),
|
| 895 | .header.cmd = UVC_CMD_RETR_SECRET,
|
| 896 | .secret_idx = secret_idx,
|
| 897 | .buf_addr = (u64)buf,
|
| 898 | .buf_size = buf_size,
|
| 899 | };
|
| 900 |
|
| 901 | uv_call(0, (u64)&uvcb);
|
| 902 |
|
| 903 | switch (uvcb.header.rc) {
|
| 904 | case UVC_RC_EXECUTED:
|
| 905 | return 0;
|
| 906 | case UVC_RC_INV_CMD:
|
| 907 | return -ENODEV;
|
| 908 | case UVC_RC_RETR_SECR_STORE_EMPTY:
|
| 909 | case UVC_RC_RETR_SECR_INV_SECRET:
|
| 910 | case UVC_RC_RETR_SECR_INV_IDX:
|
| 911 | return -ENOENT;
|
| 912 | case UVC_RC_RETR_SECR_BUF_SMALL:
|
| 913 | return -EINVAL;
|
| 914 | default:
|
| 915 | return -EIO;
|
| 916 | }
|
| 917 | }
|
| 918 | EXPORT_SYMBOL_GPL(uv_retrieve_secret);
|