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

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/pseries/papr-indices.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/pseries/papr-indices.c
Extension
.c
Size
13670 bytes
Lines
489
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations papr_indices_handle_ops = {
	.read = papr_indices_handle_read,
	.llseek = papr_rtas_common_handle_seek,
	.release = papr_rtas_common_handle_release,
};

/*
 * papr_indices_create_handle() - Create a fd-based handle for reading
 *                                indices data
 * @ubuf: Input parameters to RTAS call such as whether sensor or indicator
 *        and indice type in user memory
 *
 * Handler for PAPR_INDICES_IOC_GET ioctl command. Validates @ubuf
 * and instantiates an immutable indices "blob" for it. The blob is
 * attached to a file descriptor for reading by user space. The memory
 * backing the blob is freed when the file is released.
 *
 * The entire requested indices is retrieved by this call and all
 * necessary RTAS interactions are performed before returning the fd
 * to user space. This keeps the read handler simple and ensures that
 * the kernel can prevent interleaving of ibm,get-indices call sequences.
 *
 * Return: The installed fd number if successful, -ve errno otherwise.
 */
static long papr_indices_create_handle(struct papr_indices_io_block __user *ubuf)
{
	struct papr_rtas_sequence seq = {};
	struct rtas_get_indices_params params = {};
	int fd;

	if (get_user(params.is_sensor, &ubuf->indices.is_sensor))
		return -EFAULT;

	if (get_user(params.indice_type, &ubuf->indices.indice_type))
		return -EFAULT;

	seq = (struct papr_rtas_sequence) {
		.begin = indices_sequence_begin,
		.end = indices_sequence_end,
		.work = indices_sequence_fill_work_area,
	};

	seq.params = &params;
	fd = papr_rtas_setup_file_interface(&seq,
			&papr_indices_handle_ops, "[papr-indices]");

	return fd;
}

/*
 * Create work area with the input parameters. This function is used
 * for both ibm,set-dynamic-indicator and ibm,get-dynamic-sensor-state
 * RTAS Calls.
 */
static struct rtas_work_area *
papr_dynamic_indice_buf_from_user(struct papr_indices_io_block __user *ubuf,
				struct papr_indices_io_block *kbuf)
{
	struct rtas_work_area *work_area;
	u32 length;
	__be32 len_be;

	if (copy_from_user(kbuf, ubuf, sizeof(*kbuf)))
		return ERR_PTR(-EFAULT);


	if (!string_is_terminated(kbuf->dynamic_param.location_code_str,
			ARRAY_SIZE(kbuf->dynamic_param.location_code_str)))
		return ERR_PTR(-EINVAL);

	/*
	 * The input data in the work area should be as follows:
	 * - 32-bit integer length of the location code string,
	 *   including NULL.
	 * - Location code string, NULL terminated, identifying the
	 *   token (sensor or indicator).
	 * PAPR 2.13 - R1–7.3.18–5 ibm,set-dynamic-indicator
	 *           - R1–7.3.19–5 ibm,get-dynamic-sensor-state
	 */
	/*
	 * Length that user space passed should also include NULL
	 * terminator.
	 */
	length = strlen(kbuf->dynamic_param.location_code_str) + 1;
	if (length > LOC_CODE_SIZE)
		return ERR_PTR(-EINVAL);

	len_be = cpu_to_be32(length);

	work_area = rtas_work_area_alloc(LOC_CODE_SIZE + sizeof(u32));

Annotation

Implementation Notes