mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-03 09:23:35 +00:00
hv: asyncio: support data match of the same addr
Virtio legacy device (ver < 1.0) uses a single PIO for all virtqueues. Notifications from different virtqueues are implemented by writing virtqueue index to the PIO. Writing different values to the same addr needs to be mapped to different eventfds by asyncio. This is called data match feature of asyncio. v3 -> v4: * Update the definition of `struct asyncio_desc` Use `struct acrn_asyncio_info` inside it, instaed of defining the duplicated fileds. * Update `add_asyncio` to use `memcpy_s` rather than assigning all the fields using 5 assignment statements. * Update `asyncio_is_conflict` for coding style 120-character line is sufficient to write all conditions. * Update the checks related to `wildcard` Because we require every conditional clause to have a Boolean type in the coding guideline. v2 -> v3: No change v1 -> v2: No change Tracked-On: #8612 Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Signed-off-by: Shiqing Gao <shiqing.gao@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
parent
2737281010
commit
74bc2f7cfb
@ -553,7 +553,7 @@ int32_t hcall_asyncio_assign(__unused struct acrn_vcpu *vcpu, struct acrn_vm *ta
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (copy_from_gpa(vm, &asyncio_info, param2, sizeof(asyncio_info)) == 0) {
|
if (copy_from_gpa(vm, &asyncio_info, param2, sizeof(asyncio_info)) == 0) {
|
||||||
add_asyncio(target_vm, asyncio_info.type, asyncio_info.addr, asyncio_info.fd);
|
add_asyncio(target_vm, &asyncio_info);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -567,7 +567,7 @@ int32_t hcall_asyncio_deassign(__unused struct acrn_vcpu *vcpu, struct acrn_vm *
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (copy_from_gpa(vm, &asyncio_info, param2, sizeof(asyncio_info)) == 0) {
|
if (copy_from_gpa(vm, &asyncio_info, param2, sizeof(asyncio_info)) == 0) {
|
||||||
remove_asyncio(target_vm, asyncio_info.type, asyncio_info.addr, asyncio_info.fd);
|
remove_asyncio(target_vm, &asyncio_info);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -63,20 +63,51 @@ void reset_vm_ioreqs(struct acrn_vm *vm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd)
|
/**
|
||||||
|
* @pre vm->asyncio_lock is held
|
||||||
|
*/
|
||||||
|
static bool asyncio_is_conflict(struct acrn_vm *vm,
|
||||||
|
const struct acrn_asyncio_info *async_info)
|
||||||
|
{
|
||||||
|
struct list_head *pos;
|
||||||
|
struct asyncio_desc *p;
|
||||||
|
struct acrn_asyncio_info *info;
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
/* When either one's match_data is 0, the data matching will be skipped. */
|
||||||
|
list_for_each(pos, &vm->aiodesc_queue) {
|
||||||
|
p = container_of(pos, struct asyncio_desc, list);
|
||||||
|
info = &(p->asyncio_info);
|
||||||
|
if ((info->addr == async_info->addr) &&
|
||||||
|
(info->type == async_info->type) &&
|
||||||
|
((info->match_data == 0U) || (async_info->match_data == 0U) ||
|
||||||
|
(info->data == async_info->data))) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_asyncio(struct acrn_vm *vm, const struct acrn_asyncio_info *async_info)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
bool b_conflict;
|
||||||
|
struct asyncio_desc *desc;
|
||||||
|
|
||||||
if (addr != 0UL) {
|
if (async_info->addr != 0UL) {
|
||||||
spinlock_obtain(&vm->asyncio_lock);
|
spinlock_obtain(&vm->asyncio_lock);
|
||||||
|
b_conflict = asyncio_is_conflict(vm, async_info);
|
||||||
|
if (!b_conflict) {
|
||||||
for (i = 0U; i < ACRN_ASYNCIO_MAX; i++) {
|
for (i = 0U; i < ACRN_ASYNCIO_MAX; i++) {
|
||||||
if ((vm->aio_desc[i].addr == 0UL) && (vm->aio_desc[i].fd == 0UL)) {
|
desc = &(vm->aio_desc[i]);
|
||||||
vm->aio_desc[i].type = type;
|
if ((desc->asyncio_info.addr == 0UL) && (desc->asyncio_info.fd == 0UL)) {
|
||||||
vm->aio_desc[i].addr = addr;
|
(void)memcpy_s(&(desc->asyncio_info), sizeof(struct acrn_asyncio_info),
|
||||||
vm->aio_desc[i].fd = fd;
|
async_info, sizeof(struct acrn_asyncio_info));
|
||||||
INIT_LIST_HEAD(&vm->aio_desc[i].list);
|
INIT_LIST_HEAD(&(desc->list));
|
||||||
list_add(&vm->aio_desc[i].list, &vm->aiodesc_queue);
|
list_add(&(desc->list), &vm->aiodesc_queue);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -85,34 +116,42 @@ int add_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd)
|
|||||||
if (i == ACRN_ASYNCIO_MAX) {
|
if (i == ACRN_ASYNCIO_MAX) {
|
||||||
pr_fatal("too much fastio, would not support!");
|
pr_fatal("too much fastio, would not support!");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
spinlock_release(&vm->asyncio_lock);
|
||||||
|
pr_err("%s, already registered!", __func__);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pr_err("%s: base = 0 is not supported!", __func__);
|
pr_err("%s: base = 0 is not supported!", __func__);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int remove_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd)
|
int remove_asyncio(struct acrn_vm *vm, const struct acrn_asyncio_info *async_info)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
struct asyncio_desc *desc;
|
||||||
|
struct acrn_asyncio_info *info;
|
||||||
|
|
||||||
if (addr != 0UL) {
|
if (async_info->addr != 0UL) {
|
||||||
spinlock_obtain(&vm->asyncio_lock);
|
spinlock_obtain(&vm->asyncio_lock);
|
||||||
for (i = 0U; i < ACRN_ASYNCIO_MAX; i++) {
|
for (i = 0U; i < ACRN_ASYNCIO_MAX; i++) {
|
||||||
if ((vm->aio_desc[i].type == type)
|
desc = &(vm->aio_desc[i]);
|
||||||
&& (vm->aio_desc[i].addr == addr)
|
info = &(desc->asyncio_info);
|
||||||
&& (vm->aio_desc[i].fd == fd)) {
|
if ((info->type == async_info->type)
|
||||||
vm->aio_desc[i].type = 0U;
|
&& (info->addr == async_info->addr)
|
||||||
vm->aio_desc[i].addr = 0UL;
|
&& (info->fd == async_info->fd)
|
||||||
vm->aio_desc[i].fd = 0UL;
|
&& ((info->match_data == 0U) == (async_info->match_data == 0U))
|
||||||
list_del_init(&vm->aio_desc[i].list);
|
&& (info->data == async_info->data)) {
|
||||||
|
list_del_init(&(desc->list));
|
||||||
|
memset(desc, 0, sizeof(vm->aio_desc[0]));
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spinlock_release(&vm->asyncio_lock);
|
spinlock_release(&vm->asyncio_lock);
|
||||||
if (i == ACRN_ASYNCIO_MAX) {
|
if (i == ACRN_ASYNCIO_MAX) {
|
||||||
pr_fatal("Failed to find asyncio req on addr: %lx!", addr);
|
pr_fatal("Failed to find asyncio req on addr: %lx!", async_info->addr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pr_err("%s: base = 0 is not supported!", __func__);
|
pr_err("%s: base = 0 is not supported!", __func__);
|
||||||
@ -129,8 +168,10 @@ static struct asyncio_desc *get_asyncio_desc(struct acrn_vcpu *vcpu, const struc
|
|||||||
{
|
{
|
||||||
uint64_t addr = 0UL;
|
uint64_t addr = 0UL;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
uint64_t value;
|
||||||
struct list_head *pos;
|
struct list_head *pos;
|
||||||
struct asyncio_desc *iter_desc;
|
struct asyncio_desc *iter_desc;
|
||||||
|
struct acrn_asyncio_info *iter_info;
|
||||||
struct acrn_vm *vm = vcpu->vm;
|
struct acrn_vm *vm = vcpu->vm;
|
||||||
struct asyncio_desc *ret = NULL;
|
struct asyncio_desc *ret = NULL;
|
||||||
struct shared_buf *sbuf =
|
struct shared_buf *sbuf =
|
||||||
@ -140,11 +181,13 @@ static struct asyncio_desc *get_asyncio_desc(struct acrn_vcpu *vcpu, const struc
|
|||||||
switch (io_req->io_type) {
|
switch (io_req->io_type) {
|
||||||
case ACRN_IOREQ_TYPE_PORTIO:
|
case ACRN_IOREQ_TYPE_PORTIO:
|
||||||
addr = io_req->reqs.pio_request.address;
|
addr = io_req->reqs.pio_request.address;
|
||||||
|
value = io_req->reqs.pio_request.value;
|
||||||
type = ACRN_ASYNCIO_PIO;
|
type = ACRN_ASYNCIO_PIO;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACRN_IOREQ_TYPE_MMIO:
|
case ACRN_IOREQ_TYPE_MMIO:
|
||||||
addr = io_req->reqs.mmio_request.address;
|
addr = io_req->reqs.mmio_request.address;
|
||||||
|
value = io_req->reqs.mmio_request.value;
|
||||||
type = ACRN_ASYNCIO_MMIO;
|
type = ACRN_ASYNCIO_MMIO;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -155,7 +198,9 @@ static struct asyncio_desc *get_asyncio_desc(struct acrn_vcpu *vcpu, const struc
|
|||||||
spinlock_obtain(&vm->asyncio_lock);
|
spinlock_obtain(&vm->asyncio_lock);
|
||||||
list_for_each(pos, &vm->aiodesc_queue) {
|
list_for_each(pos, &vm->aiodesc_queue) {
|
||||||
iter_desc = container_of(pos, struct asyncio_desc, list);
|
iter_desc = container_of(pos, struct asyncio_desc, list);
|
||||||
if ((iter_desc->addr == addr) && (iter_desc->type == type)) {
|
iter_info = &(iter_desc->asyncio_info);
|
||||||
|
if ((iter_info->addr == addr) && (iter_info->type == type) &&
|
||||||
|
((iter_info->match_data == 0U) || (iter_info->data == value))) {
|
||||||
ret = iter_desc;
|
ret = iter_desc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -713,7 +758,7 @@ emulate_io(struct acrn_vcpu *vcpu, struct io_request *io_req)
|
|||||||
*/
|
*/
|
||||||
aio_desc = get_asyncio_desc(vcpu, io_req);
|
aio_desc = get_asyncio_desc(vcpu, io_req);
|
||||||
if (aio_desc) {
|
if (aio_desc) {
|
||||||
status = acrn_insert_asyncio(vcpu, aio_desc->fd);
|
status = acrn_insert_asyncio(vcpu, aio_desc->asyncio_info.fd);
|
||||||
} else {
|
} else {
|
||||||
status = acrn_insert_request(vcpu, io_req);
|
status = acrn_insert_request(vcpu, io_req);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
|
@ -41,9 +41,7 @@ struct io_request {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct asyncio_desc {
|
struct asyncio_desc {
|
||||||
uint32_t type;
|
struct acrn_asyncio_info asyncio_info;
|
||||||
uint64_t addr;
|
|
||||||
uint64_t fd;
|
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -293,9 +291,9 @@ void deinit_emul_io(struct acrn_vm *vm);
|
|||||||
|
|
||||||
int init_asyncio(struct acrn_vm *vm, uint64_t *hva);
|
int init_asyncio(struct acrn_vm *vm, uint64_t *hva);
|
||||||
|
|
||||||
int add_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd);
|
int add_asyncio(struct acrn_vm *vm, const struct acrn_asyncio_info *async_info);
|
||||||
|
|
||||||
int remove_asyncio(struct acrn_vm *vm, uint32_t type, uint64_t addr, uint64_t fd);
|
int remove_asyncio(struct acrn_vm *vm, const struct acrn_asyncio_info *async_info);
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
@ -346,8 +346,10 @@ struct acrn_io_request_buffer {
|
|||||||
|
|
||||||
struct acrn_asyncio_info {
|
struct acrn_asyncio_info {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
uint32_t match_data;
|
||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
uint64_t fd;
|
uint64_t fd;
|
||||||
|
uint64_t data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user