1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
/*
* Generic VM initialization for x86-64 NUMA setups.
* Copyright 2002,2003 Andi Kleen, SuSE Labs.
* Adapted for Xen: Ryan Harper <ryanh@us.ibm.com>
*/
#include <xen/init.h>
#include <xen/mm.h>
#include <xen/nodemask.h>
#include <xen/numa.h>
#include <asm/acpi.h>
#include <asm/e820.h>
#ifndef Dprintk
#define Dprintk(x...)
#endif
/* from proto.h */
#define round_up(x,y) ((((x)+(y))-1) & (~((y)-1)))
/*
* Keep BIOS's CPU2node information, should not be used for memory allocaion
*/
nodeid_t apicid_to_node[MAX_LOCAL_APIC] = {
[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
};
s8 acpi_numa = 0;
int __init arch_numa_setup(const char *opt)
{
#ifdef CONFIG_ACPI_NUMA
if ( !strncmp(opt, "noacpi", 6) )
{
numa_off = false;
acpi_numa = -1;
return 0;
}
#endif
return -EINVAL;
}
bool arch_numa_disabled(void)
{
return acpi_numa < 0;
}
bool __init arch_numa_unavailable(void)
{
return acpi_numa <= 0;
}
/*
* Setup early cpu_to_node.
*
* Populate cpu_to_node[] only if x86_cpu_to_apicid[],
* and apicid_to_node[] tables have valid entries for a CPU.
* This means we skip cpu_to_node[] initialisation for NUMA
* emulation and faking node case (when running a kernel compiled
* for NUMA on a non NUMA box), which is OK as cpu_to_node[]
* is already initialized in a round robin manner at numa_init_array,
* prior to this call, and this initialization is good enough
* for the fake NUMA cases.
*/
void __init init_cpu_to_node(void)
{
unsigned int i;
nodeid_t node;
for ( i = 0; i < nr_cpu_ids; i++ )
{
u32 apicid = x86_cpu_to_apicid[i];
if ( apicid == BAD_APICID )
continue;
node = apicid < MAX_LOCAL_APIC ? apicid_to_node[apicid] : NUMA_NO_NODE;
if ( node == NUMA_NO_NODE || !node_online(node) )
node = 0;
numa_set_node(i, node);
}
}
unsigned int __init arch_get_dma_bitsize(void)
{
unsigned int node;
for_each_online_node(node)
if ( node_spanned_pages(node) &&
!(node_start_pfn(node) >> (32 - PAGE_SHIFT)) )
break;
if ( node >= MAX_NUMNODES )
panic("No node with memory below 4Gb\n");
/*
* Try to not reserve the whole node's memory for DMA, but dividing
* its spanned pages by (arbitrarily chosen) 4.
*/
return min_t(unsigned int,
flsl(node_start_pfn(node) + node_spanned_pages(node) / 4 - 1)
+ PAGE_SHIFT, 32);
}
int __init arch_get_ram_range(unsigned int idx, paddr_t *start, paddr_t *end)
{
if ( idx >= e820.nr_map )
return -ENOENT;
if ( e820.map[idx].type != E820_RAM )
return -ENODATA;
*start = e820.map[idx].addr;
*end = *start + e820.map[idx].size;
return 0;
}
|