162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2020 Google LLC
462306a36Sopenharmony_ci * Author: Quentin Perret <qperret@google.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <asm/kvm_pgtable.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <nvhe/early_alloc.h>
1062306a36Sopenharmony_ci#include <nvhe/memory.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistruct kvm_pgtable_mm_ops hyp_early_alloc_mm_ops;
1362306a36Sopenharmony_cis64 __ro_after_init hyp_physvirt_offset;
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistatic unsigned long base;
1662306a36Sopenharmony_cistatic unsigned long end;
1762306a36Sopenharmony_cistatic unsigned long cur;
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciunsigned long hyp_early_alloc_nr_used_pages(void)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	return (cur - base) >> PAGE_SHIFT;
2262306a36Sopenharmony_ci}
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_civoid *hyp_early_alloc_contig(unsigned int nr_pages)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	unsigned long size = (nr_pages << PAGE_SHIFT);
2762306a36Sopenharmony_ci	void *ret = (void *)cur;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	if (!nr_pages)
3062306a36Sopenharmony_ci		return NULL;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	if (end - cur < size)
3362306a36Sopenharmony_ci		return NULL;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	cur += size;
3662306a36Sopenharmony_ci	memset(ret, 0, size);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	return ret;
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_civoid *hyp_early_alloc_page(void *arg)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	return hyp_early_alloc_contig(1);
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic void hyp_early_alloc_get_page(void *addr) { }
4762306a36Sopenharmony_cistatic void hyp_early_alloc_put_page(void *addr) { }
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_civoid hyp_early_alloc_init(void *virt, unsigned long size)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	base = cur = (unsigned long)virt;
5262306a36Sopenharmony_ci	end = base + size;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	hyp_early_alloc_mm_ops.zalloc_page = hyp_early_alloc_page;
5562306a36Sopenharmony_ci	hyp_early_alloc_mm_ops.phys_to_virt = hyp_phys_to_virt;
5662306a36Sopenharmony_ci	hyp_early_alloc_mm_ops.virt_to_phys = hyp_virt_to_phys;
5762306a36Sopenharmony_ci	hyp_early_alloc_mm_ops.get_page = hyp_early_alloc_get_page;
5862306a36Sopenharmony_ci	hyp_early_alloc_mm_ops.put_page = hyp_early_alloc_put_page;
5962306a36Sopenharmony_ci}
60