uboot/board/xen/xenguest_arm64/xenguest_arm64.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * (C) 2013
   4 * David Feng <fenghua@phytium.com.cn>
   5 * Sharma Bhupesh <bhupesh.sharma@freescale.com>
   6 *
   7 * (C) 2020 EPAM Systems Inc
   8 */
   9
  10#include <common.h>
  11#include <cpu_func.h>
  12#include <dm.h>
  13#include <errno.h>
  14#include <malloc.h>
  15#include <xen.h>
  16#include <asm/global_data.h>
  17
  18#include <asm/io.h>
  19#include <asm/armv8/mmu.h>
  20#include <asm/xen.h>
  21#include <asm/xen/hypercall.h>
  22#include <asm/xen/system.h>
  23
  24#include <linux/compiler.h>
  25
  26#include <xen/gnttab.h>
  27#include <xen/hvm.h>
  28
  29DECLARE_GLOBAL_DATA_PTR;
  30
  31int board_init(void)
  32{
  33        return 0;
  34}
  35
  36/*
  37 * Use fdt provided by Xen: according to
  38 * https://www.kernel.org/doc/Documentation/arm64/booting.txt
  39 * x0 is the physical address of the device tree blob (dtb) in system RAM.
  40 * This is stored in rom_pointer during low level init.
  41 */
  42void *board_fdt_blob_setup(int *err)
  43{
  44        *err = 0;
  45        if (fdt_magic(rom_pointer[0]) != FDT_MAGIC) {
  46                *err = -ENXIO;
  47                return NULL;
  48        }
  49        return (void *)rom_pointer[0];
  50}
  51
  52#define MAX_MEM_MAP_REGIONS 5
  53static struct mm_region xen_mem_map[MAX_MEM_MAP_REGIONS];
  54struct mm_region *mem_map = xen_mem_map;
  55
  56static int get_next_memory_node(const void *blob, int mem)
  57{
  58        do {
  59                mem = fdt_node_offset_by_prop_value(blob, mem,
  60                                                    "device_type", "memory", 7);
  61        } while (!fdtdec_get_is_enabled(blob, mem));
  62
  63        return mem;
  64}
  65
  66static int setup_mem_map(void)
  67{
  68        int i = 0, ret, mem, reg = 0;
  69        struct fdt_resource res;
  70        const void *blob = gd->fdt_blob;
  71        u64 gfn;
  72        phys_addr_t gnttab_base;
  73        phys_size_t gnttab_sz;
  74
  75        /*
  76         * Add "magic" region which is used by Xen to provide some essentials
  77         * for the guest: we need console and xenstore.
  78         */
  79        ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_CONSOLE_PFN, &gfn);
  80        if (ret < 0) {
  81                printf("%s: Can't get HVM_PARAM_CONSOLE_PFN, ret %d\n",
  82                       __func__, ret);
  83                return -EINVAL;
  84        }
  85
  86        xen_mem_map[i].virt = PFN_PHYS(gfn);
  87        xen_mem_map[i].phys = PFN_PHYS(gfn);
  88        xen_mem_map[i].size = PAGE_SIZE;
  89        xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
  90                                PTE_BLOCK_INNER_SHARE);
  91        i++;
  92
  93        ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_STORE_PFN, &gfn);
  94        if (ret < 0) {
  95                printf("%s: Can't get HVM_PARAM_STORE_PFN, ret %d\n",
  96                       __func__, ret);
  97                return -EINVAL;
  98        }
  99
 100        xen_mem_map[i].virt = PFN_PHYS(gfn);
 101        xen_mem_map[i].phys = PFN_PHYS(gfn);
 102        xen_mem_map[i].size = PAGE_SIZE;
 103        xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 104                                PTE_BLOCK_INNER_SHARE);
 105        i++;
 106
 107        /* Get Xen's suggested physical page assignments for the grant table. */
 108        get_gnttab_base(&gnttab_base, &gnttab_sz);
 109
 110        xen_mem_map[i].virt = gnttab_base;
 111        xen_mem_map[i].phys = gnttab_base;
 112        xen_mem_map[i].size = gnttab_sz;
 113        xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 114                                PTE_BLOCK_INNER_SHARE);
 115        i++;
 116
 117        mem = get_next_memory_node(blob, -1);
 118        if (mem < 0) {
 119                printf("%s: Missing /memory node\n", __func__);
 120                return -EINVAL;
 121        }
 122
 123        for (; i < MAX_MEM_MAP_REGIONS; i++) {
 124                ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
 125                if (ret == -FDT_ERR_NOTFOUND) {
 126                        reg = 0;
 127                        mem = get_next_memory_node(blob, mem);
 128                        if (mem == -FDT_ERR_NOTFOUND)
 129                                break;
 130
 131                        ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
 132                        if (ret == -FDT_ERR_NOTFOUND)
 133                                break;
 134                }
 135                if (ret != 0) {
 136                        printf("No reg property for memory node\n");
 137                        return -EINVAL;
 138                }
 139
 140                xen_mem_map[i].virt = (phys_addr_t)res.start;
 141                xen_mem_map[i].phys = (phys_addr_t)res.start;
 142                xen_mem_map[i].size = (phys_size_t)(res.end - res.start + 1);
 143                xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 144                                        PTE_BLOCK_INNER_SHARE);
 145        }
 146        return 0;
 147}
 148
 149void enable_caches(void)
 150{
 151        /* Re-setup the memory map as BSS gets cleared after relocation. */
 152        setup_mem_map();
 153        icache_enable();
 154        dcache_enable();
 155}
 156
 157/* Read memory settings from the Xen provided device tree. */
 158int dram_init(void)
 159{
 160        int ret;
 161
 162        ret = fdtdec_setup_mem_size_base();
 163        if (ret < 0)
 164                return ret;
 165        /* Setup memory map, so MMU page table size can be estimated. */
 166        return setup_mem_map();
 167}
 168
 169int dram_init_banksize(void)
 170{
 171        return fdtdec_setup_memory_banksize();
 172}
 173
 174/*
 175 * Board specific reset that is system reset.
 176 */
 177void reset_cpu(void)
 178{
 179}
 180
 181int ft_system_setup(void *blob, struct bd_info *bd)
 182{
 183        return 0;
 184}
 185
 186int ft_board_setup(void *blob, struct bd_info *bd)
 187{
 188        return 0;
 189}
 190
 191int print_cpuinfo(void)
 192{
 193        printf("Xen virtual CPU\n");
 194        return 0;
 195}
 196
 197void board_cleanup_before_linux(void)
 198{
 199        xen_fini();
 200}
 201