virt: acrn: add shared buffer interface

In ACRN, the shared buffer is created to shared data between hypervisor,
kernel and device model (in userpace). This buffer can be allocated and
initialized by kernel or device model.

Add hypercall to register shared buffer(sbuf) to ACRN hyperviosr. The
'vm_id' is used to indicate who owns this sbuf. The 'buffer' is the base
address for sbuf.

Signed-off-by: Conghui <conghui.chen@intel.com>
Reviewed-by: Fei Li <fei1.li@intel.com>
This commit is contained in:
Conghui 2022-10-14 10:44:32 +08:00 committed by wenlingz
parent f123b28d5d
commit 3243a21d5d
5 changed files with 150 additions and 1 deletions

View File

@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_ACRN_HSM) := acrn.o
acrn-y := hsm.o vm.o mm.o ioreq.o ioeventfd.o irqfd.o
acrn-y := hsm.o vm.o mm.o ioreq.o ioeventfd.o irqfd.o sbuf.o

View File

@ -35,6 +35,7 @@
#define HC_ID_MEM_BASE 0x40UL
#define HC_VM_SET_MEMORY_REGIONS _HC_ID(HC_ID, HC_ID_MEM_BASE + 0x02)
#define HC_SET_SBUF _HC_ID(HC_ID, HC_ID_MEM_BASE + 0x04)
#define HC_ID_PCI_BASE 0x50UL
#define HC_SET_PTDEV_INTR _HC_ID(HC_ID, HC_ID_PCI_BASE + 0x03)
@ -175,6 +176,18 @@ static inline long hcall_set_ioreq_buffer(u64 vmid, u64 buffer)
return acrn_hypercall2(HC_SET_IOREQ_BUFFER, vmid, buffer);
}
/**
* hcall_set_asyncio_buffer() - Set up the shared buffer.
* @vmid: User VM ID
* @buffer: Service VM GPA of the shared buffer
*
* Return: 0 on success, <0 on failure
*/
static inline long hcall_set_sbuf(u64 vmid, u64 buffer)
{
return acrn_hypercall2(HC_SET_SBUF, vmid, buffer);
}
/**
* hcall_notify_req_finish() - Notify ACRN Hypervisor of I/O request completion.
* @vmid: User VM ID

63
drivers/virt/acrn/sbuf.c Normal file
View File

@ -0,0 +1,63 @@
// SPDX-License-Identifier: GPL-2.0
/*
* ACRN shared buffer
*
* Copyright (c) 2022 Intel Corporation. All rights reserved.
*
* Authors:
* Li Fei <fei1.li@intel.com>
* Chen Conghui <conghui.chen@intel.com>
*/
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/hypervisor.h>
#include <asm/acrn.h>
#include "sbuf.h"
static inline bool sbuf_is_empty(shared_buf_t *sbuf)
{
return (sbuf->head == sbuf->tail);
}
static inline __u32 sbuf_next_ptr(__u32 pos,
__u32 span, __u32 scope)
{
pos += span;
pos = (pos >= scope) ? (pos - scope) : pos;
return pos;
}
void *acrn_sbuf_get_data_ptr(shared_buf_t *sbuf)
{
if (sbuf_is_empty(sbuf))
return NULL;
return (void *)sbuf + SBUF_HEAD_SIZE + sbuf->head;
}
void acrn_sbuf_move_next(shared_buf_t *sbuf)
{
sbuf->head = sbuf_next_ptr(sbuf->head, sbuf->ele_size, sbuf->size);
}
int acrn_sbuf_setup(uint16_t vm_id, uint16_t vcpu_id, __u32 sbuf_id, __u64 gpa)
{
struct acrn_sbuf_param *asp;
int ret;
if (x86_hyper_type != X86_HYPER_ACRN)
return -ENODEV;
asp = kzalloc(sizeof(*asp), GFP_KERNEL);
if (!asp)
return -ENOMEM;
asp->vcpu_id = vcpu_id;
asp->sbuf_id = sbuf_id;
asp->gpa = gpa;
ret = hcall_set_sbuf(vm_id, virt_to_phys(asp));
kfree(asp);
return ret;
}

21
drivers/virt/acrn/sbuf.h Normal file
View File

@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
/*
* ACRN shared buffer
*
* Copyright (c) 2022 Intel Corporation. All rights reserved.
*
* Authors:
* Li Fei <fei1.li@intel.com>
* Chen Conghui <conghui.chen@intel.com>
*/
#ifndef SHARED_BUF_H
#define SHARED_BUF_H
#include <asm/acrn.h>
#include "acrn_drv.h"
int acrn_sbuf_setup(uint16_t vm_id, uint16_t vcpu_id, __u32 sbuf_id, __u64 gpa);
void *acrn_sbuf_get_data_ptr(shared_buf_t *sbuf);
void acrn_sbuf_move_next(struct shared_buf *sbuf);
#endif /* SHARED_BUF_H */

View File

@ -479,6 +479,43 @@ struct acrn_vdev {
__u8 args[128];
};
#define SBUF_MAGIC 0x5aa57aa71aa13aa3
#define SBUF_MAX_SIZE (1ULL << 22)
#define SBUF_HEAD_SIZE 64
/* sbuf flags */
#define OVERRUN_CNT_EN (1ULL << 0) /* whether overrun counting is enabled */
#define OVERWRITE_EN (1ULL << 1) /* whether overwrite is enabled */
/**
* (sbuf) head + buf (store (ele_num - 1) elements at most)
* buffer empty: tail == head
* buffer full: (tail + ele_size) % size == head
*
* Base of memory for elements
* |
* |
* ---------------------------------------------------------------------------------------
* | shared_buf_t | raw data (ele_size)| raw date (ele_size) | ... | raw data (ele_size) |
* ---------------------------------------------------------------------------------------
* |
* |
* shared_buf_t *buf
*/
/* Make sure sizeof(shared_buf_t) == SBUF_HEAD_SIZE */
typedef struct shared_buf {
__u64 magic;
__u32 ele_num; /* number of elements */
__u32 ele_size; /* sizeof of elements */
__u32 head; /* offset from base, to read */
__u32 tail; /* offset from base, to write */
__u64 flags;
__u32 overrun_cnt; /* count of overrun */
__u32 size; /* ele_num * ele_size */
__u32 padding[6];
} __attribute__((aligned(64))) shared_buf_t;
/**
* struct acrn_msi_entry - Info for injecting a MSI interrupt to a VM
* @msi_addr: MSI addr[19:12] with dest vCPU ID
@ -580,6 +617,21 @@ struct acrn_irqfd {
struct acrn_msi_entry msi;
};
/**
* struct acrn_sbuf_param - Data to register a share buffer by hypercall
* @vcpu_id: Id of the vcpu which own this sbuf.
* ACRN_INVALID_CPUID means the sbuf is belong to a VM.
* @reserved: Reserved field.
* @sbuf_id: Type of the sbuf.
* @gpa: physcial address of the sbuf.
*/
struct acrn_sbuf_param {
__u16 vcpu_id;
__u16 reserved;
__u32 sbuf_id;
__u64 gpa;
};
/* The ioctl type, documented in ioctl-number.rst */
#define ACRN_IOCTL_TYPE 0xA2