Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eff7e541 authored by Elliot Berman's avatar Elliot Berman Committed by Murali Nalajala
Browse files

haven: hcall: Add Haven hypercall interface



Add common Haven hypercall interface implementing all of the doorbell
APIs and required message queue APIs for an initial message queue
driver.

Change-Id: I2f4cbe99b76d115a42e86d1a43f361e4793a9723
Signed-off-by: default avatarElliot Berman <eberman@codeaurora.org>
parent 77c2c036
Loading
Loading
Loading
Loading
+273 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 */
#ifndef __HH_HCALL_H
#define __HH_HCALL_H

#include <linux/err.h>
#include <linux/types.h>

#include <linux/haven/hcall_common.h>
#include <linux/haven/hh_common.h>
#include <asm/haven/hcall.h>

struct hh_hcall_hyp_identify_resp {
	u64 api_info;
	u64 flags[3];
};

static inline int hh_hcall_hyp_identify(struct hh_hcall_hyp_identify_resp *resp)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6000,
		(struct hh_hcall_args){ 0 },
		&_resp);

	if (!ret && resp) {
		resp->api_info = _resp.resp0;
		resp->flags[0] = _resp.resp1;
		resp->flags[1] = _resp.resp2;
		resp->flags[2] = _resp.resp3;
	}

	return ret < 0 ? ret : 0;
}

static inline int hh_hcall_dbl_bind(hh_capid_t dbl_capid, hh_capid_t vic_capid,
				    hh_virq_handle_t virq_info)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6010,
		(struct hh_hcall_args){ dbl_capid, vic_capid, virq_info },
		&_resp);

	return ret;
}

static inline int hh_hcall_dbl_unbind(hh_capid_t dbl_capid)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6011,
		(struct hh_hcall_args){ dbl_capid },
		&_resp);

	return ret;
}

struct hh_hcall_dbl_send_resp {
	u64 old_flags;
};

static inline int hh_hcall_dbl_send(hh_capid_t dbl_capid,
				    hh_dbl_flags_t new_flags,
				    struct hh_hcall_dbl_send_resp *resp)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6012,
		(struct hh_hcall_args){ dbl_capid, new_flags },
		&_resp);

	if (!ret && resp)
		resp->old_flags = _resp.resp1;

	return ret;
}

struct hh_hcall_dbl_recv_resp {
	u64 old_flags;
};

static inline int hh_hcall_dbl_recv(hh_capid_t dbl_capid,
				    hh_dbl_flags_t clear_flags,
				    struct hh_hcall_dbl_recv_resp *resp)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6013,
		(struct hh_hcall_args){ dbl_capid, clear_flags },
		&_resp);

	if (!ret && resp)
		resp->old_flags = _resp.resp1;

	return ret;
}

static inline int hh_hcall_dbl_reset(hh_capid_t dbl_capid)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6014,
		(struct hh_hcall_args){ dbl_capid },
		&_resp);

	return ret;
}

static inline int hh_hcall_dbl_mask(hh_capid_t dbl_capid,
				    hh_dbl_flags_t enable_mask,
				    hh_dbl_flags_t ack_mask)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6015,
		(struct hh_hcall_args){ dbl_capid, enable_mask, ack_mask },
		&_resp);

	return ret;
}

static inline int hh_hcall_msgq_bind_send(hh_capid_t msgq_capid,
					  hh_capid_t vic_capid,
					  hh_virq_handle_t virq_info)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6017,
		(struct hh_hcall_args){ msgq_capid, vic_capid, virq_info },
		&_resp);

	return ret;
}

static inline int hh_hcall_msgq_bind_recv(hh_capid_t msgq_capid,
					  hh_capid_t vic_capid,
					  hh_virq_handle_t virq_info)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6018,
		(struct hh_hcall_args){ msgq_capid, vic_capid, virq_info },
		&_resp);

	return ret;
}

static inline int hh_hcall_msgq_unbind_send(hh_capid_t msgq_capid)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6019,
		(struct hh_hcall_args){ msgq_capid },
		&_resp);

	return ret;
}

static inline int hh_hcall_msgq_unbind_recv(hh_capid_t msgq_capid)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x601A,
		(struct hh_hcall_args){ msgq_capid },
		&_resp);

	return ret;
}

struct hh_hcall_msgq_send_resp {
	bool not_full;
};

static inline int hh_hcall_msgq_send(hh_capid_t msgq_capid, size_t size,
				     void *data, u64 send_flags,
				     struct hh_hcall_msgq_send_resp *resp)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x601B,
		(struct hh_hcall_args){ msgq_capid, size, (unsigned long)data,
					send_flags },
		&_resp);

	if (resp)
		resp->not_full = _resp.resp1;

	return ret;
}

struct hh_hcall_msgq_recv_resp {
	size_t recv_size;
	bool not_empty;
};

static inline int hh_hcall_msgq_recv(hh_capid_t msgq_capid, void *buffer,
				     size_t max_size,
				     struct hh_hcall_msgq_recv_resp *resp)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x601C,
		(struct hh_hcall_args){ msgq_capid, (unsigned long)buffer,
					max_size },
		&_resp);

	if (!ret && resp) {
		resp->recv_size = _resp.resp1;
		resp->not_empty = _resp.resp2;
	}

	return ret;
}

static inline int hh_hcall_msgq_flush(hh_capid_t msgq_capid)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x601D,
		(struct hh_hcall_args){ msgq_capid },
		&_resp);

	return ret;
}

static inline int hh_hcall_msgq_configure_send(hh_capid_t msgq_capid,
					       long not_full_threshold,
					       long not_full_delay)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x601F,
		(struct hh_hcall_args){ msgq_capid, not_full_threshold,
					not_full_delay, -1 },
		&_resp);

	return ret;
}

static inline int hh_hcall_msgq_configure_recv(hh_capid_t msgq_capid,
					       long not_empty_threshold,
					       long not_empty_delay)
{
	int ret;
	struct hh_hcall_resp _resp = {0};

	ret = _hh_hcall(0x6020,
		(struct hh_hcall_args){ msgq_capid, not_empty_threshold,
					not_empty_delay, -1 },
		&_resp);

	return ret;
}

#endif
+18 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
 */
#ifndef __HH_HCALL_COMMON_H
#define __HH_HCALL_COMMON_H

struct hh_hcall_args {
	unsigned long arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7;
};

struct hh_hcall_resp {
	unsigned long resp0, resp1, resp2, resp3, resp4, resp5, resp6, resp7;
};

typedef u16 hh_hcall_fnid_t;

#endif