+ PAGE_SHIFT, 32);
}
+/**
+ * @brief Retrieves the RAM range for a given index from the e820 memory map.
+ *
+ * This function fetches the starting and ending addresses of a RAM range
+ * specified by the given index idx from the e820 memory map.
+ *
+ * @param idx The index of the RAM range in the e820 memory map to retrieve.
+ * @param start Pointer to store the starting address of the RAM range.
+ * @param end Pointer to store the exclusive ending address of the RAM range.
+ *
+ * @return 0 on success, -ENOENT if the index is out of bounds,
+ * or -ENODATA if the memory map at index idx is not of type E820_RAM.
+ */
int __init arch_get_ram_range(unsigned int idx, paddr_t *start, paddr_t *end)
{
if ( idx >= e820.nr_map )
share_hotadd_m2p_table(&info);
transfer_pages_to_heap(&info);
+ /* Update the node's present pages (like the total_pages of the system) */
+ NODE_DATA(node)->node_present_pages += epfn - spfn;
+
return 0;
destroy_m2p:
#include <xen/nodemask.h>
#include <xen/numa.h>
#include <xen/param.h>
+#include <xen/pfn.h>
#include <xen/sched.h>
#include <xen/softirq.h>
return shift;
}
-/* Initialize NODE_DATA given nodeid and start/end */
+/**
+ * @brief Initialize a NUMA node's node_data structure at boot.
+ *
+ * It is given the NUMA node's index in the node_data array as well
+ * as the start and exclusive end address of the node's memory span
+ * as arguments and initializes the node_data entry with this information.
+ *
+ * It then initializes the total number of usable memory pages within
+ * the NUMA node's memory span using the arch_get_ram_range() function.
+ *
+ * @param nodeid The index into the node_data array for the node.
+ * @param start The starting physical address of the node's memory range.
+ * @param end The exclusive ending physical address of the node's memory range.
+ */
void __init setup_node_bootmem(nodeid_t nodeid, paddr_t start, paddr_t end)
{
unsigned long start_pfn = paddr_to_pfn(start);
unsigned long end_pfn = paddr_to_pfn(end);
-
- NODE_DATA(nodeid)->node_start_pfn = start_pfn;
- NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn;
+ struct node_data *node = NODE_DATA(nodeid);
+ unsigned int idx = 0;
+ int err;
+
+ node->node_start_pfn = start_pfn;
+ node->node_spanned_pages = end_pfn - start_pfn;
+ node->node_present_pages = 0;
+
+ /* Calculate the number of present RAM pages within the node */
+ do {
+ paddr_t ram_start, ram_end;
+
+ err = arch_get_ram_range(idx++, &ram_start, &ram_end);
+ if ( !err && ram_start < end && ram_end > start )
+ node->node_present_pages += PFN_DOWN(min(ram_end, end)) -
+ PFN_UP(max(ram_start, start));
+ } while ( err != -ENOENT );
node_set_online(nodeid);
}
extern unsigned long memnodemapsize;
extern nodeid_t *memnodemap;
+/* The memory information of NUMA nodes in the node_data[] array */
struct node_data {
+ /* The starting page frame number (lowest pfn) of the NUMA node */
unsigned long node_start_pfn;
+
+ /*
+ * The number of pages spanned by the NUMA node, including memory holes.
+ * Used for the pyhsical memory range when scrubbing unallocated memory.
+ */
unsigned long node_spanned_pages;
+
+ /*
+ * Number of usable memory pages that are available in this NUMA node.
+ * The sum of these values from all NUMA nodes reflects total_pages.
+ * The Xen Hypervisor does not use this field internally, but it is useful
+ * for reporting the memory information of NUMA nodes to management tools.
+ */
+ unsigned long node_present_pages;
};
extern struct node_data node_data[];
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define node_spanned_pages(nid) (NODE_DATA(nid)->node_spanned_pages)
+#define node_present_pages(nid) (NODE_DATA(nid)->node_present_pages)
#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
NODE_DATA(nid)->node_spanned_pages)
extern mfn_t first_valid_mfn;
#define node_spanned_pages(nid) (max_page - mfn_x(first_valid_mfn))
+#define node_present_pages(nid) total_pages
#define node_start_pfn(nid) mfn_x(first_valid_mfn)
#define __node_distance(a, b) 20