linux/arch/powerpc/platforms/pseries/svm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Secure VM platform
   4 *
   5 * Copyright 2018 IBM Corporation
   6 * Author: Anshuman Khandual <khandual@linux.vnet.ibm.com>
   7 */
   8
   9#include <linux/mm.h>
  10#include <asm/machdep.h>
  11#include <asm/svm.h>
  12#include <asm/swiotlb.h>
  13#include <asm/ultravisor.h>
  14
  15static int __init init_svm(void)
  16{
  17        if (!is_secure_guest())
  18                return 0;
  19
  20        /* Don't release the SWIOTLB buffer. */
  21        ppc_swiotlb_enable = 1;
  22
  23        /*
  24         * Since the guest memory is inaccessible to the host, devices always
  25         * need to use the SWIOTLB buffer for DMA even if dma_capable() says
  26         * otherwise.
  27         */
  28        swiotlb_force = SWIOTLB_FORCE;
  29
  30        /* Share the SWIOTLB buffer with the host. */
  31        swiotlb_update_mem_attributes();
  32
  33        return 0;
  34}
  35machine_early_initcall(pseries, init_svm);
  36
  37int set_memory_encrypted(unsigned long addr, int numpages)
  38{
  39        if (!PAGE_ALIGNED(addr))
  40                return -EINVAL;
  41
  42        uv_unshare_page(PHYS_PFN(__pa(addr)), numpages);
  43
  44        return 0;
  45}
  46
  47int set_memory_decrypted(unsigned long addr, int numpages)
  48{
  49        if (!PAGE_ALIGNED(addr))
  50                return -EINVAL;
  51
  52        uv_share_page(PHYS_PFN(__pa(addr)), numpages);
  53
  54        return 0;
  55}
  56
  57/* There's one dispatch log per CPU. */
  58#define NR_DTL_PAGE (DISPATCH_LOG_BYTES * CONFIG_NR_CPUS / PAGE_SIZE)
  59
  60static struct page *dtl_page_store[NR_DTL_PAGE];
  61static long dtl_nr_pages;
  62
  63static bool is_dtl_page_shared(struct page *page)
  64{
  65        long i;
  66
  67        for (i = 0; i < dtl_nr_pages; i++)
  68                if (dtl_page_store[i] == page)
  69                        return true;
  70
  71        return false;
  72}
  73
  74void dtl_cache_ctor(void *addr)
  75{
  76        unsigned long pfn = PHYS_PFN(__pa(addr));
  77        struct page *page = pfn_to_page(pfn);
  78
  79        if (!is_dtl_page_shared(page)) {
  80                dtl_page_store[dtl_nr_pages] = page;
  81                dtl_nr_pages++;
  82                WARN_ON(dtl_nr_pages >= NR_DTL_PAGE);
  83                uv_share_page(pfn, 1);
  84        }
  85}
  86