162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include <linux/slab.h>
362306a36Sopenharmony_ci#include <linux/types.h>
462306a36Sopenharmony_ci#include <linux/mm.h>
562306a36Sopenharmony_ci#include <linux/fs.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <xen/page.h>
862306a36Sopenharmony_ci#include <xen/xenbus.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "xenfs.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cistatic ssize_t xsd_read(struct file *file, char __user *buf,
1362306a36Sopenharmony_ci			    size_t size, loff_t *off)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	const char *str = (const char *)file->private_data;
1662306a36Sopenharmony_ci	return simple_read_from_buffer(buf, size, off, str, strlen(str));
1762306a36Sopenharmony_ci}
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic int xsd_release(struct inode *inode, struct file *file)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	kfree(file->private_data);
2262306a36Sopenharmony_ci	return 0;
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic int xsd_kva_open(struct inode *inode, struct file *file)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	file->private_data = (void *)kasprintf(GFP_KERNEL, "0x%p",
2862306a36Sopenharmony_ci					       xen_store_interface);
2962306a36Sopenharmony_ci	if (!file->private_data)
3062306a36Sopenharmony_ci		return -ENOMEM;
3162306a36Sopenharmony_ci	return 0;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic int xsd_kva_mmap(struct file *file, struct vm_area_struct *vma)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	size_t size = vma->vm_end - vma->vm_start;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if ((size > PAGE_SIZE) || (vma->vm_pgoff != 0))
3962306a36Sopenharmony_ci		return -EINVAL;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (remap_pfn_range(vma, vma->vm_start,
4262306a36Sopenharmony_ci			    virt_to_pfn(xen_store_interface),
4362306a36Sopenharmony_ci			    size, vma->vm_page_prot))
4462306a36Sopenharmony_ci		return -EAGAIN;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	return 0;
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ciconst struct file_operations xsd_kva_file_ops = {
5062306a36Sopenharmony_ci	.open = xsd_kva_open,
5162306a36Sopenharmony_ci	.mmap = xsd_kva_mmap,
5262306a36Sopenharmony_ci	.read = xsd_read,
5362306a36Sopenharmony_ci	.release = xsd_release,
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic int xsd_port_open(struct inode *inode, struct file *file)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	file->private_data = (void *)kasprintf(GFP_KERNEL, "%d",
5962306a36Sopenharmony_ci					       xen_store_evtchn);
6062306a36Sopenharmony_ci	if (!file->private_data)
6162306a36Sopenharmony_ci		return -ENOMEM;
6262306a36Sopenharmony_ci	return 0;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ciconst struct file_operations xsd_port_file_ops = {
6662306a36Sopenharmony_ci	.open = xsd_port_open,
6762306a36Sopenharmony_ci	.read = xsd_read,
6862306a36Sopenharmony_ci	.release = xsd_release,
6962306a36Sopenharmony_ci};
70