lkml.org 
[lkml]   [2008]   [Jul]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: [PATCH 1/2] Add /sys/firmware/memmap
On Fri, 27 Jun 2008 13:12:54 +0200 Bernhard Walle <bwalle@suse.de> wrote:

> This patch adds /sys/firmware/memmap interface that represents the BIOS
> (or Firmware) provided memory map. The tree looks like:
>
> /sys/firmware/memmap/0/start (hex number)
> end (hex number)
> type (string)
> ... /1/start
> end
> type
>
> With the following shell snippet one can print the memory map in the same form
> the kernel prints itself when booting on x86 (the E820 map).
>
> --------- 8< --------------------------
> #!/bin/sh
> cd /sys/firmware/memmap
> for dir in * ; do
> start=$(cat $dir/start)
> end=$(cat $dir/end)
> type=$(cat $dir/type)
> printf "%016x-%016x (%s)\n" $start $[ $end +1] "$type"
> done
> --------- >8 --------------------------
>
> That patch only provides the needed interface:
>
> 1. The sysfs interface.
> 2. The structure and enumeration definition.
> 3. The function firmware_map_add() and firmware_map_add_early()
> that should be called from architecture code (E820/EFI, for
> example) to add the contents to the interface.
>
> If the kernel is compiled without CONFIG_FIRMWARE_MEMMAP, the interface does
> nothing without cluttering the architecture-specific code with #ifdef's.
>
> The purpose of the new interface is kexec: While /proc/iomem represents
> the *used* memory map (e.g. modified via kernel parameters like 'memmap'
> and 'mem'), the /sys/firmware/memmap tree represents the unmodified memory
> map provided via the firmware. So kexec can:
>
> - use the original memory map for rebooting,
> - use the /proc/iomem for setting up the ELF core headers for kdump
> case that should only represent the memory of the system.
>
> The patch has been tested on i386 and x86_64.
>
> ...
>
> +/*
> + * Firmware memory map entries
> + */
> +static LIST_HEAD(map_entries);

Alarm bells. Please add a comment explaining why no locking is needed
for this.

> +/**
> + * Common implementation of firmware_map_add() and firmware_map_add_early()
> + * which expects a pre-allocated struct firmware_map_entry.
> + *
> + * @start: Start of the memory range.
> + * @end: End of the memory range (inclusive).
> + * @type: Type of the memory range.
> + * @entry: Pre-allocated (either kmalloc() or bootmem allocator), uninitialised
> + * entry.
> + */

Busted kerneldoc. It should start with

/**
* firmware_map_add_entry - <stuff>

> +static int firmware_map_add_entry(resource_size_t start, resource_size_t end,
> + const char *type,
> + struct firmware_map_entry *entry)
> +{
> + BUG_ON(start > end);
> +
> + entry->start = start;
> + entry->end = end;
> + entry->type = type;
> + INIT_LIST_HEAD(&entry->list);
> + kobject_init(&entry->kobj, &memmap_ktype);
> +
> + list_add_tail(&entry->list, &map_entries);
> +
> + return 0;
> +}
> +
> +/*
> + * See <linux/firmware-map.h> for documentation.
> + */
> +int firmware_map_add(resource_size_t start, resource_size_t end,
> + const char *type)
> +{
> + struct firmware_map_entry *entry;
> +
> + entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
> + WARN_ON(!entry);

Actually, kmalloc() would have warned already.

> + if (!entry)
> + return -ENOMEM;
> +
> + return firmware_map_add_entry(start, end, type, entry);
> +}
> +
>
> ...
>
> +static ssize_t start_show(struct firmware_map_entry *entry, char *buf)
> +{
> + return snprintf(buf, PAGE_SIZE, "0x%llx\n", entry->start);
> +}
> +
> +static ssize_t end_show(struct firmware_map_entry *entry, char *buf)
> +{
> + return snprintf(buf, PAGE_SIZE, "0x%llx\n", entry->end);
> +}

Printing a resource_size_t needs a cast to `unsigned long long' to
avoid printk warnings.

> +static ssize_t type_show(struct firmware_map_entry *entry, char *buf)
> +{
> + return snprintf(buf, PAGE_SIZE, "%s\n", entry->type);
> +}
> +
> +#define to_memmap_attr(_attr) container_of(_attr, struct memmap_attribute, attr)
> +#define to_memmap_entry(obj) container_of(obj, struct firmware_map_entry, kobj)
> +
> +static ssize_t memmap_attr_show(struct kobject *kobj,
> + struct attribute *attr, char *buf)
> +{
> + struct firmware_map_entry *entry = to_memmap_entry(kobj);
> + struct memmap_attribute *memmap_attr = to_memmap_attr(attr);
> +
> + return memmap_attr->show(entry, buf);
> +}
> +
> +/*
> + * Initialises stuff and adds the entries in the map_entries list to
> + * sysfs. Important is that firmware_map_add() and firmware_map_add_early()
> + * must be called before late_initcall.

Please update the comment to provide the reason why this is important.

> + */
> +static int __init memmap_init(void)
> +{
> + int i = 0;
> + struct firmware_map_entry *entry;
> + struct kset *memmap_kset;
> +
> + memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
> + WARN_ON(!memmap_kset);
> + if (!memmap_kset)
> + return -ENOMEM;

Actually, you can do

if (WARN_ON(!memmap_kset))
return -ENOMEM;

(multiple instances)

> + list_for_each_entry(entry, &map_entries, list) {
> + entry->kobj.kset = memmap_kset;
> + kobject_add(&entry->kobj, NULL, "%d", i++);

kobject_add() can fail.

I'd suggest that you enable CONFIG_ENABLE_MUST_CHECK in your usualconfig.

> + }
> +
> + return 0;
> +}
> +late_initcall(memmap_init);
> +
>
> ...
>
> +/**
> + * Adds a firmware mapping entry. This function uses kmalloc() for memory
> + * allocation. Use firmware_map_add_early() if you want to use the bootmem
> + * allocator.
> + *
> + * That function must be called before late_initcall.
> + *
> + * @start: Start of the memory range.
> + * @end: End of the memory range (inclusive).
> + * @type: Type of the memory range.
> + *
> + * Returns 0 on success, or -ENOMEM if no memory could be allocated.
> + */
> +int firmware_map_add(resource_size_t start, resource_size_t end,
> + const char *type);

More busted kernedoc (multiple instances)

Please document C functions at the definition site, not in the header file.

a) because otherwise the documentation gets splattered across
different files (eg - static functions?)

b) principle of least surprise: that's where people expect to find it.

> +/**
> + * Adds a firmware mapping entry. This function uses the bootmem allocator
> + * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
> + *
> + * That function must be called before late_initcall.
> + *
> + * @start: Start of the memory range.
> + * @end: End of the memory range (inclusive).
> + * @type: Type of the memory range.
> + *
> + * Returns 0 on success, or -ENOMEM if no memory could be allocated.
> + */
> +int firmware_map_add_early(resource_size_t start, resource_size_t end,
> + const char *type);
> +
> +#else /* CONFIG_FIRMWARE_MEMMAP */
> +
> +static inline int firmware_map_add(resource_size_t start, resource_size_t end,
> + const char *type)
> +{
> + return 0;
> +}
> +
> +static inline int firmware_map_add_early(resource_size_t start,
> + resource_size_t end, const char *type)
> +{
> + return 0;
> +}
> +
> +#endif /* CONFIG_FIRMWARE_MEMMAP */
> +
> +#endif /* _LINUX_FIRMWARE_MAP_H */



\
 
 \ /
  Last update: 2008-07-12 02:39    [W:0.105 / U:0.044 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site