Apply remaining minor fixups from Gunyah v13 patches: https://lore.kernel.org/all/20230509204801.2824351-1-quic_eberman@quicinc.com/ Bug: 279506910 Change-Id: I1a596b9df29d210c51b612845e4a1aafbea00441 Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
207 lines
5 KiB
C
207 lines
5 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _LINUX_GUNYAH_H
|
|
#define _LINUX_GUNYAH_H
|
|
|
|
#include <linux/bitfield.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/limits.h>
|
|
#include <linux/mailbox_controller.h>
|
|
#include <linux/mailbox_client.h>
|
|
#include <linux/types.h>
|
|
|
|
/* Matches resource manager's resource types for VM_GET_HYP_RESOURCES RPC */
|
|
enum gh_resource_type {
|
|
GH_RESOURCE_TYPE_BELL_TX = 0,
|
|
GH_RESOURCE_TYPE_BELL_RX = 1,
|
|
GH_RESOURCE_TYPE_MSGQ_TX = 2,
|
|
GH_RESOURCE_TYPE_MSGQ_RX = 3,
|
|
GH_RESOURCE_TYPE_VCPU = 4,
|
|
};
|
|
|
|
struct gh_resource {
|
|
enum gh_resource_type type;
|
|
u64 capid;
|
|
unsigned int irq;
|
|
|
|
struct list_head list;
|
|
u32 rm_label;
|
|
};
|
|
|
|
/**
|
|
* Gunyah Message Queues
|
|
*/
|
|
|
|
#define GH_MSGQ_MAX_MSG_SIZE 240
|
|
|
|
struct gh_msgq_tx_data {
|
|
size_t length;
|
|
bool push;
|
|
char data[];
|
|
};
|
|
|
|
struct gh_msgq_rx_data {
|
|
size_t length;
|
|
char data[GH_MSGQ_MAX_MSG_SIZE];
|
|
};
|
|
|
|
struct gh_msgq {
|
|
struct gh_resource *tx_ghrsc;
|
|
struct gh_resource *rx_ghrsc;
|
|
|
|
/* msgq private */
|
|
int last_ret; /* Linux error, not GH_STATUS_* */
|
|
struct mbox_chan mbox_chan;
|
|
struct mbox_controller mbox;
|
|
struct tasklet_struct txdone_tasklet;
|
|
};
|
|
|
|
|
|
int gh_msgq_init(struct device *parent, struct gh_msgq *msgq, struct mbox_client *cl,
|
|
struct gh_resource *tx_ghrsc, struct gh_resource *rx_ghrsc);
|
|
void gh_msgq_remove(struct gh_msgq *msgq);
|
|
|
|
static inline struct mbox_chan *gh_msgq_chan(struct gh_msgq *msgq)
|
|
{
|
|
return &msgq->mbox.chans[0];
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/* Common arch-independent definitions for Gunyah hypercalls */
|
|
|
|
#define GH_CAPID_INVAL U64_MAX
|
|
#define GH_VMID_ROOT_VM 0xff
|
|
|
|
enum gh_error {
|
|
GH_ERROR_OK = 0,
|
|
GH_ERROR_UNIMPLEMENTED = -1,
|
|
GH_ERROR_RETRY = -2,
|
|
|
|
GH_ERROR_ARG_INVAL = 1,
|
|
GH_ERROR_ARG_SIZE = 2,
|
|
GH_ERROR_ARG_ALIGN = 3,
|
|
|
|
GH_ERROR_NOMEM = 10,
|
|
|
|
GH_ERROR_ADDR_OVFL = 20,
|
|
GH_ERROR_ADDR_UNFL = 21,
|
|
GH_ERROR_ADDR_INVAL = 22,
|
|
|
|
GH_ERROR_DENIED = 30,
|
|
GH_ERROR_BUSY = 31,
|
|
GH_ERROR_IDLE = 32,
|
|
|
|
GH_ERROR_IRQ_BOUND = 40,
|
|
GH_ERROR_IRQ_UNBOUND = 41,
|
|
|
|
GH_ERROR_CSPACE_CAP_NULL = 50,
|
|
GH_ERROR_CSPACE_CAP_REVOKED = 51,
|
|
GH_ERROR_CSPACE_WRONG_OBJ_TYPE = 52,
|
|
GH_ERROR_CSPACE_INSUF_RIGHTS = 53,
|
|
GH_ERROR_CSPACE_FULL = 54,
|
|
|
|
GH_ERROR_MSGQUEUE_EMPTY = 60,
|
|
GH_ERROR_MSGQUEUE_FULL = 61,
|
|
};
|
|
|
|
/**
|
|
* gh_error_remap() - Remap Gunyah hypervisor errors into a Linux error code
|
|
* @gh_error: Gunyah hypercall return value
|
|
*/
|
|
static inline int gh_error_remap(enum gh_error gh_error)
|
|
{
|
|
switch (gh_error) {
|
|
case GH_ERROR_OK:
|
|
return 0;
|
|
case GH_ERROR_NOMEM:
|
|
return -ENOMEM;
|
|
case GH_ERROR_DENIED:
|
|
case GH_ERROR_CSPACE_CAP_NULL:
|
|
case GH_ERROR_CSPACE_CAP_REVOKED:
|
|
case GH_ERROR_CSPACE_WRONG_OBJ_TYPE:
|
|
case GH_ERROR_CSPACE_INSUF_RIGHTS:
|
|
case GH_ERROR_CSPACE_FULL:
|
|
return -EACCES;
|
|
case GH_ERROR_BUSY:
|
|
case GH_ERROR_IDLE:
|
|
return -EBUSY;
|
|
case GH_ERROR_IRQ_BOUND:
|
|
case GH_ERROR_IRQ_UNBOUND:
|
|
case GH_ERROR_MSGQUEUE_FULL:
|
|
case GH_ERROR_MSGQUEUE_EMPTY:
|
|
return -EIO;
|
|
case GH_ERROR_UNIMPLEMENTED:
|
|
case GH_ERROR_RETRY:
|
|
return -EOPNOTSUPP;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
enum gh_api_feature {
|
|
GH_FEATURE_DOORBELL = 1,
|
|
GH_FEATURE_MSGQUEUE = 2,
|
|
GH_FEATURE_VCPU = 5,
|
|
GH_FEATURE_MEMEXTENT = 6,
|
|
};
|
|
|
|
bool arch_is_gh_guest(void);
|
|
|
|
#define GH_API_V1 1
|
|
|
|
/* Other bits reserved for future use and will be zero */
|
|
#define GH_API_INFO_API_VERSION_MASK GENMASK_ULL(13, 0)
|
|
#define GH_API_INFO_BIG_ENDIAN BIT_ULL(14)
|
|
#define GH_API_INFO_IS_64BIT BIT_ULL(15)
|
|
#define GH_API_INFO_VARIANT_MASK GENMASK_ULL(63, 56)
|
|
|
|
struct gh_hypercall_hyp_identify_resp {
|
|
u64 api_info;
|
|
u64 flags[3];
|
|
};
|
|
|
|
static inline u16 gh_api_version(const struct gh_hypercall_hyp_identify_resp *gh_api)
|
|
{
|
|
return FIELD_GET(GH_API_INFO_API_VERSION_MASK, gh_api->api_info);
|
|
}
|
|
|
|
void gh_hypercall_hyp_identify(struct gh_hypercall_hyp_identify_resp *hyp_identity);
|
|
|
|
enum gh_error gh_hypercall_bell_send(u64 capid, u64 new_flags, u64 *old_flags);
|
|
enum gh_error gh_hypercall_bell_set_mask(u64 capid, u64 enable_mask, u64 ack_mask);
|
|
|
|
#define GH_HYPERCALL_MSGQ_TX_FLAGS_PUSH BIT(0)
|
|
|
|
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 {
|
|
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];
|
|
};
|
|
|
|
enum gh_error gh_hypercall_vcpu_run(u64 capid, u64 *resume_data,
|
|
struct gh_hypercall_vcpu_run_resp *resp);
|
|
|
|
#endif
|