diff --git a/include/linux/haven/hcall.h b/include/linux/haven/hcall.h new file mode 100644 index 000000000000..c39dd9d81893 --- /dev/null +++ b/include/linux/haven/hcall.h @@ -0,0 +1,273 @@ +/* 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 +#include + +#include +#include +#include + +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 diff --git a/include/linux/haven/hcall_common.h b/include/linux/haven/hcall_common.h new file mode 100644 index 000000000000..f6ada3eabd0d --- /dev/null +++ b/include/linux/haven/hcall_common.h @@ -0,0 +1,18 @@ +/* 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