diff --git a/arch/arm64/gunyah/gunyah_hypercall.c b/arch/arm64/gunyah/gunyah_hypercall.c index 2925932660f1..3d48c8650851 100644 --- a/arch/arm64/gunyah/gunyah_hypercall.c +++ b/arch/arm64/gunyah/gunyah_hypercall.c @@ -63,7 +63,7 @@ enum gh_error gh_hypercall_bell_send(u64 capid, u64 new_flags, u64 *old_flags) arm_smccc_1_1_hvc(GH_HYPERCALL_BELL_SEND, capid, new_flags, 0, &res); - if (res.a0 == GH_ERROR_OK) + if (res.a0 == GH_ERROR_OK && old_flags) *old_flags = res.a1; return res.a0; @@ -80,7 +80,7 @@ enum gh_error gh_hypercall_bell_set_mask(u64 capid, u64 enable_mask, u64 ack_mas } EXPORT_SYMBOL_GPL(gh_hypercall_bell_set_mask); -enum gh_error gh_hypercall_msgq_send(u64 capid, size_t size, void *buff, int tx_flags, bool *ready) +enum gh_error gh_hypercall_msgq_send(u64 capid, size_t size, void *buff, u64 tx_flags, bool *ready) { struct arm_smccc_res res; @@ -126,7 +126,7 @@ enum gh_error gh_hypercall_vcpu_run(u64 capid, u64 *resume_data, arm_smccc_1_2_hvc(&args, &res); if (res.a0 == GH_ERROR_OK) { - resp->state = res.a1; + resp->sized_state = res.a1; resp->state_data[0] = res.a2; resp->state_data[1] = res.a3; resp->state_data[2] = res.a4; diff --git a/drivers/virt/gunyah/gunyah_irqfd.c b/drivers/virt/gunyah/gunyah_irqfd.c index 25db65fc751e..1b7f0c5073da 100644 --- a/drivers/virt/gunyah/gunyah_irqfd.c +++ b/drivers/virt/gunyah/gunyah_irqfd.c @@ -30,13 +30,11 @@ static int irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, v { struct gh_irqfd *irqfd = container_of(wait, struct gh_irqfd, wait); __poll_t flags = key_to_poll(key); - u64 enable_mask = GH_BELL_NONBLOCK; - u64 old_flags; int ret = 0; if (flags & EPOLLIN) { if (irqfd->ghrsc) { - ret = gh_hypercall_bell_send(irqfd->ghrsc->capid, enable_mask, &old_flags); + ret = gh_hypercall_bell_send(irqfd->ghrsc->capid, 1, NULL); if (ret) pr_err_ratelimited("Failed to inject interrupt %d: %d\n", irqfd->ticket.label, ret); @@ -57,9 +55,7 @@ static void irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, p static bool gh_irqfd_populate(struct gh_vm_resource_ticket *ticket, struct gh_resource *ghrsc) { struct gh_irqfd *irqfd = container_of(ticket, struct gh_irqfd, ticket); - u64 enable_mask = GH_BELL_NONBLOCK; - u64 ack_mask = ~0; - int ret = 0; + int ret; if (irqfd->ghrsc) { pr_warn("irqfd%d already got a Gunyah resource. Check if multiple resources with same label were configured.\n", @@ -69,7 +65,14 @@ static bool gh_irqfd_populate(struct gh_vm_resource_ticket *ticket, struct gh_re irqfd->ghrsc = ghrsc; if (irqfd->level) { - ret = gh_hypercall_bell_set_mask(irqfd->ghrsc->capid, enable_mask, ack_mask); + /* Configure the bell to trigger when bit 0 is asserted (see + * irq_wakeup) and for bell to automatically clear bit 0 once + * received by the VM (ack_mask). need to make sure bit 0 is cleared right away, + * otherwise the line will never be deasserted. Emulating edge + * trigger interrupt does not need to set either mask + * because irq is listed only once per gh_hypercall_bell_send + */ + ret = gh_hypercall_bell_set_mask(irqfd->ghrsc->capid, 1, 1); if (ret) pr_warn("irq %d couldn't be set as level triggered. Might cause IRQ storm if asserted\n", irqfd->ticket.label); diff --git a/drivers/virt/gunyah/gunyah_vcpu.c b/drivers/virt/gunyah/gunyah_vcpu.c index c329184e5fb6..acb565c3a680 100644 --- a/drivers/virt/gunyah/gunyah_vcpu.c +++ b/drivers/virt/gunyah/gunyah_vcpu.c @@ -41,19 +41,6 @@ struct gh_vcpu { struct kref kref; }; -/* VCPU is ready to run */ -#define GH_VCPU_STATE_READY 0 -/* VCPU is sleeping until an interrupt arrives */ -#define GH_VCPU_STATE_EXPECTS_WAKEUP 1 -/* VCPU is powered off */ -#define GH_VCPU_STATE_POWERED_OFF 2 -/* VCPU is blocked in EL2 for unspecified reason */ -#define GH_VCPU_STATE_BLOCKED 3 -/* VCPU has returned for MMIO READ */ -#define GH_VCPU_ADDRSPACE_VMMIO_READ 4 -/* VCPU has returned for MMIO WRITE */ -#define GH_VCPU_ADDRSPACE_VMMIO_WRITE 5 - static void vcpu_release(struct kref *kref) { struct gh_vcpu *vcpu = container_of(kref, struct gh_vcpu, kref); @@ -245,7 +232,7 @@ static int gh_vcpu_run(struct gh_vcpu *vcpu) break; default: pr_warn_ratelimited("Unknown vCPU state: %llx\n", - vcpu_run_resp.state); + vcpu_run_resp.sized_state); schedule(); break; } diff --git a/include/linux/gunyah.h b/include/linux/gunyah.h index e4de51381041..ddea1ea9ce9c 100644 --- a/include/linux/gunyah.h +++ b/include/linux/gunyah.h @@ -33,11 +33,6 @@ struct gh_resource { u32 rm_label; }; -/** - * Gunyah Doorbells - */ -#define GH_BELL_NONBLOCK BIT(32) - /** * Gunyah Message Queues */ @@ -181,12 +176,28 @@ enum gh_error gh_hypercall_bell_set_mask(u64 capid, u64 enable_mask, u64 ack_mas #define GH_HYPERCALL_MSGQ_TX_FLAGS_PUSH BIT(0) -enum gh_error gh_hypercall_msgq_send(u64 capid, size_t size, void *buff, int tx_flags, bool *ready); +enum gh_error gh_hypercall_msgq_send(u64 capid, size_t size, void *buff, u64 tx_flags, bool *ready); enum gh_error gh_hypercall_msgq_recv(u64 capid, void *buff, size_t size, size_t *recv_size, bool *ready); struct gh_hypercall_vcpu_run_resp { - u64 state; + union { + enum { + /* VCPU is ready to run */ + GH_VCPU_STATE_READY = 0, + /* VCPU is sleeping until an interrupt arrives */ + GH_VCPU_STATE_EXPECTS_WAKEUP = 1, + /* VCPU is powered off */ + GH_VCPU_STATE_POWERED_OFF = 2, + /* VCPU is blocked in EL2 for unspecified reason */ + GH_VCPU_STATE_BLOCKED = 3, + /* VCPU has returned for MMIO READ */ + GH_VCPU_ADDRSPACE_VMMIO_READ = 4, + /* VCPU has returned for MMIO WRITE */ + GH_VCPU_ADDRSPACE_VMMIO_WRITE = 5, + } state; + u64 sized_state; + }; u64 state_data[3]; };