Skip to content

Commit ae11e20

Browse files
paolonighaxtibal
authored andcommitted
/dev/mem: Add initial documentation of memory_open() and mem_fops
This patch proposes initial kernel-doc documentation for memory_open() and most of the functions in the mem_fops structure. The format used for the specifications follows the guidelines defined in Documentation/doc-guide/code-specifications.rst Signed-off-by: Gabriele Paoloni <gpaoloni@redhat.com>
1 parent 9bee79e commit ae11e20

1 file changed

Lines changed: 225 additions & 6 deletions

File tree

drivers/char/mem.c

Lines changed: 225 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,54 @@ static inline bool should_stop_iteration(void)
7575
return signal_pending(current);
7676
}
7777

78-
/*
79-
* This funcion reads the *physical* memory. The f_pos points directly to the
80-
* memory location.
78+
/**
79+
* read_mem - read from physical memory (/dev/mem).
80+
* @file: struct file associated with /dev/mem.
81+
* @buf: user-space buffer to copy data to.
82+
* @count: number of bytes to read.
83+
* @ppos: pointer to the current file position, representing the physical
84+
* address to read from.
85+
*
86+
* This function checks if the requested physical memory range is valid
87+
* and accessible by the user, then it copies data to the input
88+
* user-space buffer up to the requested number of bytes.
89+
*
90+
* Function's expectations:
91+
*
92+
* 1. This function shall check if the value pointed by ppos exceeds the
93+
* maximum addressable physical address;
94+
*
95+
* 2. This function shall check if the physical address range to be read
96+
* is valid (i.e. it falls within a memory block and if it can be mapped
97+
* to the kernel address space);
98+
*
99+
* 3. For each memory page falling in the requested physical range
100+
* [ppos, ppos + count - 1]:
101+
* 3.1. this function shall check if user space access is allowed (if
102+
* config STRICT_DEVMEM is not set, access is always granted);
103+
*
104+
* 3.2. if access is allowed, the memory content from the page range falling
105+
* within the requested physical range shall be copied to the user space
106+
* buffer;
107+
*
108+
* 3.3. zeros shall be copied to the user space buffer (for the page range
109+
* falling within the requested physical range):
110+
* 3.3.1. if access to the memory page is restricted or,
111+
* 3.2.2. if the current page is page 0 on HW architectures where page 0 is
112+
* not mapped.
113+
*
114+
* 4. The file position '*ppos' shall be advanced by the number of bytes
115+
* successfully copied to user space (including zeros).
116+
*
117+
* Context: process context.
118+
*
119+
* Return:
120+
* * the number of bytes copied to user on success
121+
* * %-EFAULT - the requested address range is not valid or a fault happened
122+
* when copying to user-space (i.e. copy_from_kernel_nofault() failed)
123+
* * %-EPERM - access to any of the required physical pages is not allowed
124+
* * %-ENOMEM - out of memory error for auxiliary kernel buffers supporting
125+
* the operation of copying content from the physical pages
81126
*/
82127
static ssize_t read_mem(struct file *file, char __user *buf,
83128
size_t count, loff_t *ppos)
@@ -166,6 +211,54 @@ static ssize_t read_mem(struct file *file, char __user *buf,
166211
return err;
167212
}
168213

214+
/**
215+
* write_mem - write to physical memory (/dev/mem).
216+
* @file: struct file associated with /dev/mem.
217+
* @buf: user-space buffer containing the data to write.
218+
* @count: number of bytes to write.
219+
* @ppos: pointer to the current file position, representing the physical
220+
* address to write to.
221+
*
222+
* This function checks if the target physical memory range is valid
223+
* and accessible by the user, then it writes data from the input
224+
* user-space buffer up to the requested number of bytes.
225+
*
226+
* Function's expectations:
227+
* 1. This function shall check if the value pointed by ppos exceeds the
228+
* maximum addressable physical address;
229+
*
230+
* 2. This function shall check if the physical address range to be written
231+
* is valid (i.e. it falls within a memory block and if it can be mapped
232+
* to the kernel address space);
233+
*
234+
* 3. For each memory page falling in the physical range to be written
235+
* [ppos, ppos + count - 1]:
236+
* 3.1. this function shall check if user space access is allowed (if
237+
* config STRICT_DEVMEM is not set, access is always granted);
238+
*
239+
* 3.2. the content from the user space buffer shall be copied to the page
240+
* range falling within the physical range to be written if access is
241+
* allowed;
242+
*
243+
* 3.3. the data to be copied from the user space buffer (for the page range
244+
* falling within the range to be written) shall be skipped:
245+
* 3.3.1. if access to the memory page is restricted or,
246+
* 3.3.2. if the current page is page 0 on HW architectures where page 0
247+
* is not mapped.
248+
*
249+
* 4. The file position '*ppos' shall be advanced by the number of bytes
250+
* successfully copied from user space (including skipped bytes).
251+
*
252+
* Context: process context.
253+
*
254+
* Return:
255+
* * the number of bytes copied from user-space on success
256+
* * %-EFBIG - the value pointed by ppos exceeds the maximum addressable
257+
* physical address
258+
* * %-EFAULT - the physical address range is not valid or no bytes could
259+
* be copied from user-space
260+
* * %-EPERM - access to any of the required pages is not allowed
261+
*/
169262
static ssize_t write_mem(struct file *file, const char __user *buf,
170263
size_t count, loff_t *ppos)
171264
{
@@ -322,6 +415,42 @@ static const struct vm_operations_struct mmap_mem_ops = {
322415
#endif
323416
};
324417

418+
/**
419+
* mmap_mem - map physical memory into user space (/dev/mem).
420+
* @file: file structure for the device.
421+
* @vma: virtual memory area structure describing the user mapping.
422+
*
423+
* This function checks if the requested physical memory range is valid
424+
* and accessible by the user, then it maps the physical memory range to
425+
* user-mode address space.
426+
*
427+
* Function's expectations:
428+
* 1. This function shall check if the requested physical address range to be
429+
* mapped fits within the maximum addressable physical range;
430+
*
431+
* 2. This function shall check if the requested physical range corresponds to
432+
* a valid physical range and if access is allowed on it (if config STRICT_DEVMEM
433+
* is not set, access is always allowed);
434+
*
435+
* 3. This function shall check if the input virtual memory area can be used for
436+
* a private mapping (always OK if there is an MMU);
437+
*
438+
* 4. This function shall set the virtual memory area operations to
439+
* &mmap_mem_ops;
440+
*
441+
* 5. This function shall establish a mapping between the user-space
442+
* virtual memory area described by vma and the physical memory
443+
* range specified by vma->vm_pgoff and size;
444+
*
445+
* Context: process context.
446+
*
447+
* Return:
448+
* * 0 on success
449+
* * %-EAGAIN - invalid or unsupported mapping requested (remap_pfn_range()
450+
* fails)
451+
* * %-EINVAL - requested physical range to be mapped is not valid
452+
* * %-EPERM - no permission to access the requested physical range
453+
*/
325454
static int mmap_mem(struct file *file, struct vm_area_struct *vma)
326455
{
327456
size_t size = vma->vm_end - vma->vm_start;
@@ -563,13 +692,47 @@ static loff_t null_lseek(struct file *file, loff_t offset, int orig)
563692
return file->f_pos = 0;
564693
}
565694

566-
/*
695+
/**
696+
* memory_lseek - change the file position.
697+
* @file: file structure for the device.
698+
* @offset: file offset to seek to.
699+
* @orig: where to start seeking from (see whence in the llseek manpage).
700+
*
701+
* This function changes the file position according to the input offset
702+
* and orig parameters.
703+
*
704+
* Function's expectations:
705+
* 1. This function shall lock the semaphore of the inode corresponding to the
706+
* input file before any operation and unlock it before returning.
707+
*
708+
* 2. This function shall check the orig value and accordingly:
709+
* 2.1. if it is equal to SEEK_CUR, the current file position shall be
710+
* incremented by the input offset;
711+
* 2.2. if it is equal to SEEK_SET, the current file position shall be
712+
* set to the input offset value;
713+
* 2.3. any other value shall result in an error condition.
714+
*
715+
* 3. Before writing the current file position, the new position value
716+
* shall be checked to not overlap with Linux ERRNO values.
717+
*
718+
* Assumptions of Use:
719+
* 1. the input file pointer is expected to be valid.
720+
*
721+
* Notes:
567722
* The memory devices use the full 32/64 bits of the offset, and so we cannot
568723
* check against negative addresses: they are ok. The return value is weird,
569724
* though, in that case (0).
570725
*
571-
* also note that seeking relative to the "end of file" isn't supported:
572-
* it has no meaning, so it returns -EINVAL.
726+
* Also note that seeking relative to the "end of file" isn't supported:
727+
* it has no meaning, so passing orig equal to SEEK_END returns -EINVAL.
728+
*
729+
* Context: process context, locks/unlocks inode->i_rwsem
730+
*
731+
* Return:
732+
* * the new file position on success
733+
* * %-EOVERFLOW - the new position value equals or exceeds
734+
* (unsigned long long) -MAX_ERRNO
735+
* * %-EINVAL - the orig parameter is invalid
573736
*/
574737
static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
575738
{
@@ -597,6 +760,35 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
597760
return ret;
598761
}
599762

763+
/**
764+
* open_port - open the I/O port device (/dev/port).
765+
* @inode: inode of the device file.
766+
* @filp: file structure for the device.
767+
*
768+
* This function checks if the caller can access the port device and sets
769+
* the f_mapping pointer of filp to the i_mapping pointer of inode.
770+
*
771+
* Function's expectations:
772+
* 1. This function shall check if the caller has sufficient capabilities to
773+
* perform raw I/O access;
774+
*
775+
* 2. This function shall check if the kernel is locked down with the
776+
* &LOCKDOWN_DEV_MEM restriction;
777+
*
778+
* 3. If the input inode corresponds to /dev/mem, the f_mapping pointer
779+
* of the input file structure shall be set to the i_mapping pointer
780+
* of the input inode;
781+
*
782+
* Assumptions of Use:
783+
* 1. The input inode and filp are expected to be valid.
784+
*
785+
* Context: process context.
786+
*
787+
* Return:
788+
* * 0 on success
789+
* * %-EPERM - caller lacks the required capability (CAP_SYS_RAWIO)
790+
* * any error returned by securty_locked_down()
791+
*/
600792
static int open_port(struct inode *inode, struct file *filp)
601793
{
602794
int rc;
@@ -704,6 +896,33 @@ static const struct memdev {
704896
#endif
705897
};
706898

899+
/**
900+
* memory_open - set the filp f_op to the memory device fops and invoke open().
901+
* @inode: inode of the device file.
902+
* @filp: file structure for the device.
903+
*
904+
* Function's expectations:
905+
* 1. This function shall retrieve the minor number associated with the input
906+
* inode and the memory device corresponding to such minor number;
907+
*
908+
* 2. The file operations pointer shall be set to the memory device file operations;
909+
*
910+
* 3. The file mode member of the input filp shall be OR'd with the device mode;
911+
*
912+
* 4. The memory device open() file operation shall be invoked.
913+
*
914+
* Assumptions of Use:
915+
* 1. The input inode and filp are expected to be non-NULL.
916+
*
917+
* Context: process context.
918+
*
919+
* Return:
920+
* * 0 on success
921+
* * %-ENXIO - the minor number corresponding to the input inode cannot be
922+
* associated with any device or the corresponding device has a NULL fops
923+
* pointer
924+
* * any error returned by the device specific open function pointer
925+
*/
707926
static int memory_open(struct inode *inode, struct file *filp)
708927
{
709928
int minor;

0 commit comments

Comments
 (0)