Skip to content

Commit cfdd96c

Browse files
author
Mamatha Inamdar
committed
powerpc/pseries: Receive payload with ibm,receive-hvpipe-msg RTAS
JIRA: https://issues.redhat.com/browse/RHEL-101849 Conflicts: - Use rtas_token() instead of rtas_function_token() - Use 0 for RTAS_SUCCESS (This definition needs upstream 9592aa5 "powerpc/rtas: Add function return status constants") commit cebdb52 Author: Haren Myneni <haren@linux.ibm.com> Date: Tue Sep 9 01:43:57 2025 -0700 powerpc/pseries: Receive payload with ibm,receive-hvpipe-msg RTAS ibm,receive-hvpipe-msg RTAS call is used to receive data from the source (Ex: Hardware Management Console) over the hypervisor pipe. The hypervisor will signal the OS via a Hypervisor Pipe Event external interrupt when data is available to be received from the pipe and the event message has the source ID and the message type such as payload or closed pipe to the specific source. The hypervisor will not generate another interrupt for the next payload until the partition reads the previous payload. It means the hvpipe is blocked and will not deliver other events for any source. The maximum data length of 4048 bytes is supported with this RTAS call right now. The user space uses read() to receive data from HMC which issues ibm,receive-hvpipe-msg RTAS and the kernel returns the buffer length (including papr_hvpipe_hdr length) to the user space for success or RTAS failure error. If the message is regarding the pipe closed, kernel just returns the papr_hvpipe_hdr with flags = HVPIPE_LOST_CONNECTION and expects the user space to close FD for the corresponding source. ibm,receive-hvpipe-msg RTAS call passes the buffer and returns the source ID from where this payload is received and the payload length. Signed-off-by: Haren Myneni <haren@linux.ibm.com> Tested-by: Shashank MS <shashank.gowda@in.ibm.com> Reviewed-by: Mahesh Salgaonkar <mahesh@linux.ibm.com> Reviewed-by: Tyrel Datwyler <tyreld@linux.ibm.com> Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com> Link: https://patch.msgid.link/20250909084402.1488456-6-haren@linux.ibm.com Signed-off-by: Mamatha Inamdar <minamdar@redhat.com>
1 parent 22bfbd4 commit cfdd96c

File tree

2 files changed

+163
-2
lines changed

2 files changed

+163
-2
lines changed

arch/powerpc/platforms/pseries/papr-hvpipe.c

Lines changed: 162 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,54 @@ static LIST_HEAD(hvpipe_src_list);
6060
* return code for failure.
6161
*/
6262

63+
/*
64+
* ibm,receive-hvpipe-msg RTAS call.
65+
* @area: Caller-provided work area buffer for results.
66+
* @srcID: Source ID returned by the RTAS call.
67+
* @bytesw: Bytes written by RTAS call to @area.
68+
*/
69+
static int rtas_ibm_receive_hvpipe_msg(struct rtas_work_area *area,
70+
u32 *srcID, u32 *bytesw)
71+
{
72+
const s32 token = rtas_token("ibm,receive-hvpipe-msg");
73+
u32 rets[2];
74+
s32 fwrc;
75+
int ret;
76+
77+
if (token == RTAS_UNKNOWN_SERVICE)
78+
return -ENOENT;
79+
80+
do {
81+
fwrc = rtas_call(token, 2, 3, rets,
82+
rtas_work_area_phys(area),
83+
rtas_work_area_size(area));
84+
85+
} while (rtas_busy_delay(fwrc));
86+
87+
switch (fwrc) {
88+
case 0: /* Success */
89+
*srcID = rets[0];
90+
*bytesw = rets[1];
91+
ret = 0;
92+
break;
93+
case RTAS_HARDWARE_ERROR:
94+
ret = -EIO;
95+
break;
96+
case RTAS_INVALID_PARAMETER:
97+
ret = -EINVAL;
98+
break;
99+
case RTAS_FUNC_NOT_SUPPORTED:
100+
ret = -EOPNOTSUPP;
101+
break;
102+
default:
103+
ret = -EIO;
104+
pr_err_ratelimited("unexpected ibm,receive-hvpipe-msg status %d\n", fwrc);
105+
break;
106+
}
107+
108+
return ret;
109+
}
110+
63111
/*
64112
* ibm,send-hvpipe-msg RTAS call
65113
* @area: Caller-provided work area buffer to send.
@@ -116,9 +164,60 @@ static struct hvpipe_source_info *hvpipe_find_source(u32 srcID)
116164
return NULL;
117165
}
118166

167+
/*
168+
* This work function collects receive buffer with recv HVPIPE
169+
* RTAS call. Called from read()
170+
* @buf: User specified buffer to copy the payload that returned
171+
* from recv HVPIPE RTAS.
172+
* @size: Size of buffer user passed.
173+
*/
174+
static int hvpipe_rtas_recv_msg(char __user *buf, int size)
175+
{
176+
struct rtas_work_area *work_area;
177+
u32 srcID, bytes_written;
178+
int ret;
179+
180+
work_area = rtas_work_area_alloc(SZ_4K);
181+
if (!work_area) {
182+
pr_err("Could not allocate RTAS buffer for recv pipe\n");
183+
return -ENOMEM;
184+
}
185+
186+
ret = rtas_ibm_receive_hvpipe_msg(work_area, &srcID,
187+
&bytes_written);
188+
if (!ret) {
189+
/*
190+
* Recv HVPIPE RTAS is successful.
191+
* When releasing FD or no one is waiting on the
192+
* specific source, issue recv HVPIPE RTAS call
193+
* so that pipe is not blocked - this func is called
194+
* with NULL buf.
195+
*/
196+
if (buf) {
197+
if (size < bytes_written) {
198+
pr_err("Received the payload size = %d, but the buffer size = %d\n",
199+
bytes_written, size);
200+
bytes_written = size;
201+
}
202+
ret = copy_to_user(buf,
203+
rtas_work_area_raw_buf(work_area),
204+
bytes_written);
205+
if (!ret)
206+
ret = bytes_written;
207+
}
208+
} else {
209+
pr_err("ibm,receive-hvpipe-msg failed with %d\n",
210+
ret);
211+
}
212+
213+
rtas_work_area_free(work_area);
214+
return ret;
215+
}
216+
119217
/*
120218
* papr_hvpipe_handle_write - Issue send HVPIPE RTAS and return
121-
* the RTAS status to the user space
219+
* the size (payload + HVPIPE_HDR_LEN) for RTAS success.
220+
* Otherwise returns the status of RTAS to the user space
122221
*/
123222
static ssize_t papr_hvpipe_handle_write(struct file *file,
124223
const char __user *buf, size_t size, loff_t *off)
@@ -215,11 +314,72 @@ static ssize_t papr_hvpipe_handle_read(struct file *file,
215314
{
216315

217316
struct hvpipe_source_info *src_info = file->private_data;
317+
struct papr_hvpipe_hdr hdr;
318+
long ret;
218319

219320
if (!src_info)
220321
return -EIO;
221322

222-
return 0;
323+
/*
324+
* Max payload is 4048 (HVPIPE_MAX_WRITE_BUFFER_SIZE)
325+
*/
326+
if ((size > (HVPIPE_HDR_LEN + HVPIPE_MAX_WRITE_BUFFER_SIZE)) ||
327+
(size < HVPIPE_HDR_LEN))
328+
return -EINVAL;
329+
330+
/*
331+
* Payload is not available to receive or source pipe
332+
* is not closed.
333+
*/
334+
if (!src_info->hvpipe_status)
335+
return 0;
336+
337+
hdr.version = 0;
338+
hdr.flags = 0;
339+
340+
/*
341+
* In case if the hvpipe has payload and also the
342+
* hypervisor closed the pipe to the source, retrieve
343+
* the payload and return to the user space first and
344+
* then notify the userspace about the hvpipe close in
345+
* next read().
346+
*/
347+
if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE)
348+
hdr.flags = HVPIPE_MSG_AVAILABLE;
349+
else if (src_info->hvpipe_status & HVPIPE_LOST_CONNECTION)
350+
hdr.flags = HVPIPE_LOST_CONNECTION;
351+
else
352+
/*
353+
* Should not be here without one of the above
354+
* flags set
355+
*/
356+
return -EIO;
357+
358+
ret = copy_to_user(buf, &hdr, HVPIPE_HDR_LEN);
359+
if (ret)
360+
return ret;
361+
362+
/*
363+
* Message event has payload, so get the payload with
364+
* recv HVPIPE RTAS.
365+
*/
366+
if (hdr.flags & HVPIPE_MSG_AVAILABLE) {
367+
ret = hvpipe_rtas_recv_msg(buf + HVPIPE_HDR_LEN,
368+
size - HVPIPE_HDR_LEN);
369+
if (ret > 0) {
370+
src_info->hvpipe_status &= ~HVPIPE_MSG_AVAILABLE;
371+
ret += HVPIPE_HDR_LEN;
372+
}
373+
} else if (hdr.flags & HVPIPE_LOST_CONNECTION) {
374+
/*
375+
* Hypervisor is closing the pipe for the specific
376+
* source. So notify user space.
377+
*/
378+
src_info->hvpipe_status &= ~HVPIPE_LOST_CONNECTION;
379+
ret = HVPIPE_HDR_LEN;
380+
}
381+
382+
return ret;
223383
}
224384

225385
/*

arch/powerpc/platforms/pseries/papr-hvpipe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
struct hvpipe_source_info {
1515
struct list_head list; /* list of sources */
1616
u32 srcID;
17+
u32 hvpipe_status;
1718
wait_queue_head_t recv_wqh; /* wake up poll() waitq */
1819
struct task_struct *tsk;
1920
};

0 commit comments

Comments
 (0)