u-boot/board/xen/xenguest_arm64/xenguest_arm64.c
Peng Fan 384d5cfe5d serial: serial_xen: Add Xen PV serial driver
Add support for Xen para-virtualized serial driver. This
driver fully supports serial console for the virtual machine.

Please note that as the driver is initialized late, so no banner
nor memory size is visible.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
2020-08-14 15:18:30 -04:00

169 lines
3.4 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* (C) 2013
* David Feng <fenghua@phytium.com.cn>
* Sharma Bhupesh <bhupesh.sharma@freescale.com>
*
* (C) 2020 EPAM Systems Inc
*/
#include <common.h>
#include <cpu_func.h>
#include <dm.h>
#include <errno.h>
#include <malloc.h>
#include <asm/io.h>
#include <asm/armv8/mmu.h>
#include <asm/xen.h>
#include <asm/xen/hypercall.h>
#include <asm/xen/system.h>
#include <linux/compiler.h>
#include <xen/hvm.h>
DECLARE_GLOBAL_DATA_PTR;
int board_init(void)
{
return 0;
}
/*
* Use fdt provided by Xen: according to
* https://www.kernel.org/doc/Documentation/arm64/booting.txt
* x0 is the physical address of the device tree blob (dtb) in system RAM.
* This is stored in rom_pointer during low level init.
*/
void *board_fdt_blob_setup(void)
{
if (fdt_magic(rom_pointer[0]) != FDT_MAGIC)
return NULL;
return (void *)rom_pointer[0];
}
#define MAX_MEM_MAP_REGIONS 5
static struct mm_region xen_mem_map[MAX_MEM_MAP_REGIONS];
struct mm_region *mem_map = xen_mem_map;
static int get_next_memory_node(const void *blob, int mem)
{
do {
mem = fdt_node_offset_by_prop_value(blob, mem,
"device_type", "memory", 7);
} while (!fdtdec_get_is_enabled(blob, mem));
return mem;
}
static int setup_mem_map(void)
{
int i = 0, ret, mem, reg = 0;
struct fdt_resource res;
const void *blob = gd->fdt_blob;
u64 gfn;
/*
* Add "magic" region which is used by Xen to provide some essentials
* for the guest: we need console.
*/
ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_CONSOLE_PFN, &gfn);
if (ret < 0) {
printf("%s: Can't get HVM_PARAM_CONSOLE_PFN, ret %d\n",
__func__, ret);
return -EINVAL;
}
xen_mem_map[i].virt = PFN_PHYS(gfn);
xen_mem_map[i].phys = PFN_PHYS(gfn);
xen_mem_map[i].size = PAGE_SIZE;
xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE);
i++;
mem = get_next_memory_node(blob, -1);
if (mem < 0) {
printf("%s: Missing /memory node\n", __func__);
return -EINVAL;
}
for (; i < MAX_MEM_MAP_REGIONS; i++) {
ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
if (ret == -FDT_ERR_NOTFOUND) {
reg = 0;
mem = get_next_memory_node(blob, mem);
if (mem == -FDT_ERR_NOTFOUND)
break;
ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
if (ret == -FDT_ERR_NOTFOUND)
break;
}
if (ret != 0) {
printf("No reg property for memory node\n");
return -EINVAL;
}
xen_mem_map[i].virt = (phys_addr_t)res.start;
xen_mem_map[i].phys = (phys_addr_t)res.start;
xen_mem_map[i].size = (phys_size_t)(res.end - res.start + 1);
xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE);
}
return 0;
}
void enable_caches(void)
{
/* Re-setup the memory map as BSS gets cleared after relocation. */
setup_mem_map();
icache_enable();
dcache_enable();
}
/* Read memory settings from the Xen provided device tree. */
int dram_init(void)
{
int ret;
ret = fdtdec_setup_mem_size_base();
if (ret < 0)
return ret;
/* Setup memory map, so MMU page table size can be estimated. */
return setup_mem_map();
}
int dram_init_banksize(void)
{
return fdtdec_setup_memory_banksize();
}
/*
* Board specific reset that is system reset.
*/
void reset_cpu(ulong addr)
{
}
int ft_system_setup(void *blob, struct bd_info *bd)
{
return 0;
}
int ft_board_setup(void *blob, struct bd_info *bd)
{
return 0;
}
int board_early_init_f(void)
{
return 0;
}
int print_cpuinfo(void)
{
printf("Xen virtual CPU\n");
return 0;
}