Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
e38eb34a
Commit
e38eb34a
authored
Nov 20, 2012
by
Russell King
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'cluster-boot-protocol' of
git://linux-arm.org/linux-2.6-lp
into devel-stable
parents
2079f30e
384a2902
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
256 additions
and
48 deletions
+256
-48
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/arm/cpus.txt
+77
-0
arch/arm/common/gic.c
arch/arm/common/gic.c
+36
-9
arch/arm/include/asm/cputype.h
arch/arm/include/asm/cputype.h
+13
-0
arch/arm/include/asm/prom.h
arch/arm/include/asm/prom.h
+2
-0
arch/arm/include/asm/smp_plat.h
arch/arm/include/asm/smp_plat.h
+17
-0
arch/arm/kernel/devtree.c
arch/arm/kernel/devtree.c
+100
-0
arch/arm/kernel/setup.c
arch/arm/kernel/setup.c
+5
-3
arch/arm/kernel/topology.c
arch/arm/kernel/topology.c
+6
-36
No files found.
Documentation/devicetree/bindings/arm/cpus.txt
0 → 100644
View file @
e38eb34a
* ARM CPUs binding description
The device tree allows to describe the layout of CPUs in a system through
the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
defining properties for every cpu.
Bindings for CPU nodes follow the ePAPR standard, available from:
http://devicetree.org
For the ARM architecture every CPU node must contain the following properties:
- device_type: must be "cpu"
- reg: property matching the CPU MPIDR[23:0] register bits
reg[31:24] bits must be set to 0
- compatible: should be one of:
"arm,arm1020"
"arm,arm1020e"
"arm,arm1022"
"arm,arm1026"
"arm,arm720"
"arm,arm740"
"arm,arm7tdmi"
"arm,arm920"
"arm,arm922"
"arm,arm925"
"arm,arm926"
"arm,arm940"
"arm,arm946"
"arm,arm9tdmi"
"arm,cortex-a5"
"arm,cortex-a7"
"arm,cortex-a8"
"arm,cortex-a9"
"arm,cortex-a15"
"arm,arm1136"
"arm,arm1156"
"arm,arm1176"
"arm,arm11mpcore"
"faraday,fa526"
"intel,sa110"
"intel,sa1100"
"marvell,feroceon"
"marvell,mohawk"
"marvell,xsc3"
"marvell,xscale"
Example:
cpus {
#size-cells = <0>;
#address-cells = <1>;
CPU0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x0>;
};
CPU1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x1>;
};
CPU2: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x100>;
};
CPU3: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x101>;
};
};
arch/arm/common/gic.c
View file @
e38eb34a
...
...
@@ -69,6 +69,14 @@ struct gic_chip_data {
static
DEFINE_RAW_SPINLOCK
(
irq_controller_lock
);
/*
* The GIC mapping of CPU interfaces does not necessarily match
* the logical CPU numbering. Let's use a mapping as returned
* by the GIC itself.
*/
#define NR_GIC_CPU_IF 8
static
u8
gic_cpu_map
[
NR_GIC_CPU_IF
]
__read_mostly
;
/*
* Supported arch specific GIC irq extension.
* Default make them NULL.
...
...
@@ -238,11 +246,11 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
unsigned
int
cpu
=
cpumask_any_and
(
mask_val
,
cpu_online_mask
);
u32
val
,
mask
,
bit
;
if
(
cpu
>=
8
||
cpu
>=
nr_cpu_ids
)
if
(
cpu
>=
NR_GIC_CPU_IF
||
cpu
>=
nr_cpu_ids
)
return
-
EINVAL
;
mask
=
0xff
<<
shift
;
bit
=
1
<<
(
cpu_logical_map
(
cpu
)
+
shift
)
;
bit
=
gic_cpu_map
[
cpu
]
<<
shift
;
raw_spin_lock
(
&
irq_controller_lock
);
val
=
readl_relaxed
(
reg
)
&
~
mask
;
...
...
@@ -349,11 +357,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
u32
cpumask
;
unsigned
int
gic_irqs
=
gic
->
gic_irqs
;
void
__iomem
*
base
=
gic_data_dist_base
(
gic
);
u32
cpu
=
cpu_logical_map
(
smp_processor_id
());
cpumask
=
1
<<
cpu
;
cpumask
|=
cpumask
<<
8
;
cpumask
|=
cpumask
<<
16
;
writel_relaxed
(
0
,
base
+
GIC_DIST_CTRL
);
...
...
@@ -366,6 +369,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
/*
* Set all global interrupts to this CPU only.
*/
cpumask
=
readl_relaxed
(
base
+
GIC_DIST_TARGET
+
0
);
for
(
i
=
32
;
i
<
gic_irqs
;
i
+=
4
)
writel_relaxed
(
cpumask
,
base
+
GIC_DIST_TARGET
+
i
*
4
/
4
);
...
...
@@ -389,8 +393,24 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
{
void
__iomem
*
dist_base
=
gic_data_dist_base
(
gic
);
void
__iomem
*
base
=
gic_data_cpu_base
(
gic
);
unsigned
int
cpu_mask
,
cpu
=
smp_processor_id
();
int
i
;
/*
* Get what the GIC says our CPU mask is.
*/
BUG_ON
(
cpu
>=
NR_GIC_CPU_IF
);
cpu_mask
=
readl_relaxed
(
dist_base
+
GIC_DIST_TARGET
+
0
);
gic_cpu_map
[
cpu
]
=
cpu_mask
;
/*
* Clear our mask from the other map entries in case they're
* still undefined.
*/
for
(
i
=
0
;
i
<
NR_GIC_CPU_IF
;
i
++
)
if
(
i
!=
cpu
)
gic_cpu_map
[
i
]
&=
~
cpu_mask
;
/*
* Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled.
...
...
@@ -646,7 +666,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
{
irq_hw_number_t
hwirq_base
;
struct
gic_chip_data
*
gic
;
int
gic_irqs
,
irq_base
;
int
gic_irqs
,
irq_base
,
i
;
BUG_ON
(
gic_nr
>=
MAX_GIC_NR
);
...
...
@@ -682,6 +702,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
gic_set_base_accessor
(
gic
,
gic_get_common_base
);
}
/*
* Initialize the CPU interface map to all CPUs.
* It will be refined as each CPU probes its ID.
*/
for
(
i
=
0
;
i
<
NR_GIC_CPU_IF
;
i
++
)
gic_cpu_map
[
i
]
=
0xff
;
/*
* For primary GICs, skip over SGIs.
* For secondary GICs, skip over PPIs, too.
...
...
@@ -737,7 +764,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
/* Convert our logical CPU mask into a physical one. */
for_each_cpu
(
cpu
,
mask
)
map
|=
1
<<
cpu_logical_map
(
cpu
)
;
map
|=
gic_cpu_map
[
cpu
]
;
/*
* Ensure that stores to Normal memory are visible to the
...
...
arch/arm/include/asm/cputype.h
View file @
e38eb34a
...
...
@@ -25,6 +25,19 @@
#define CPUID_EXT_ISAR4 "c2, 4"
#define CPUID_EXT_ISAR5 "c2, 5"
#define MPIDR_SMP_BITMASK (0x3 << 30)
#define MPIDR_SMP_VALUE (0x2 << 30)
#define MPIDR_MT_BITMASK (0x1 << 24)
#define MPIDR_HWID_BITMASK 0xFFFFFF
#define MPIDR_LEVEL_BITS 8
#define MPIDR_LEVEL_MASK ((1 << MPIDR_LEVEL_BITS) - 1)
#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK)
extern
unsigned
int
processor_id
;
#ifdef CONFIG_CPU_CP15
...
...
arch/arm/include/asm/prom.h
View file @
e38eb34a
...
...
@@ -15,6 +15,7 @@
extern
struct
machine_desc
*
setup_machine_fdt
(
unsigned
int
dt_phys
);
extern
void
arm_dt_memblock_reserve
(
void
);
extern
void
__init
arm_dt_init_cpu_maps
(
void
);
#else
/* CONFIG_OF */
...
...
@@ -24,6 +25,7 @@ static inline struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
}
static
inline
void
arm_dt_memblock_reserve
(
void
)
{
}
static
inline
void
arm_dt_init_cpu_maps
(
void
)
{
}
#endif
/* CONFIG_OF */
#endif
/* ASMARM_PROM_H */
arch/arm/include/asm/smp_plat.h
View file @
e38eb34a
...
...
@@ -5,6 +5,9 @@
#ifndef __ASMARM_SMP_PLAT_H
#define __ASMARM_SMP_PLAT_H
#include <linux/cpumask.h>
#include <linux/err.h>
#include <asm/cputype.h>
/*
...
...
@@ -48,5 +51,19 @@ static inline int cache_ops_need_broadcast(void)
*/
extern
int
__cpu_logical_map
[];
#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
/*
* Retrieve logical cpu index corresponding to a given MPIDR[23:0]
* - mpidr: MPIDR[23:0] to be used for the look-up
*
* Returns the cpu logical index or -EINVAL on look-up error
*/
static
inline
int
get_logical_index
(
u32
mpidr
)
{
int
cpu
;
for
(
cpu
=
0
;
cpu
<
nr_cpu_ids
;
cpu
++
)
if
(
cpu_logical_map
(
cpu
)
==
mpidr
)
return
cpu
;
return
-
EINVAL
;
}
#endif
arch/arm/kernel/devtree.c
View file @
e38eb34a
...
...
@@ -19,8 +19,10 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/cputype.h>
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/smp_plat.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
...
...
@@ -61,6 +63,104 @@ void __init arm_dt_memblock_reserve(void)
}
}
/*
* arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree
* and builds the cpu logical map array containing MPIDR values related to
* logical cpus
*
* Updates the cpu possible mask with the number of parsed cpu nodes
*/
void
__init
arm_dt_init_cpu_maps
(
void
)
{
/*
* Temp logical map is initialized with UINT_MAX values that are
* considered invalid logical map entries since the logical map must
* contain a list of MPIDR[23:0] values where MPIDR[31:24] must
* read as 0.
*/
struct
device_node
*
cpu
,
*
cpus
;
u32
i
,
j
,
cpuidx
=
1
;
u32
mpidr
=
is_smp
()
?
read_cpuid_mpidr
()
&
MPIDR_HWID_BITMASK
:
0
;
u32
tmp_map
[
NR_CPUS
]
=
{
[
0
...
NR_CPUS
-
1
]
=
UINT_MAX
};
bool
bootcpu_valid
=
false
;
cpus
=
of_find_node_by_path
(
"/cpus"
);
if
(
!
cpus
)
return
;
for_each_child_of_node
(
cpus
,
cpu
)
{
u32
hwid
;
pr_debug
(
" * %s...
\n
"
,
cpu
->
full_name
);
/*
* A device tree containing CPU nodes with missing "reg"
* properties is considered invalid to build the
* cpu_logical_map.
*/
if
(
of_property_read_u32
(
cpu
,
"reg"
,
&
hwid
))
{
pr_debug
(
" * %s missing reg property
\n
"
,
cpu
->
full_name
);
return
;
}
/*
* 8 MSBs must be set to 0 in the DT since the reg property
* defines the MPIDR[23:0].
*/
if
(
hwid
&
~
MPIDR_HWID_BITMASK
)
return
;
/*
* Duplicate MPIDRs are a recipe for disaster.
* Scan all initialized entries and check for
* duplicates. If any is found just bail out.
* temp values were initialized to UINT_MAX
* to avoid matching valid MPIDR[23:0] values.
*/
for
(
j
=
0
;
j
<
cpuidx
;
j
++
)
if
(
WARN
(
tmp_map
[
j
]
==
hwid
,
"Duplicate /cpu reg "
"properties in the DT
\n
"
))
return
;
/*
* Build a stashed array of MPIDR values. Numbering scheme
* requires that if detected the boot CPU must be assigned
* logical id 0. Other CPUs get sequential indexes starting
* from 1. If a CPU node with a reg property matching the
* boot CPU MPIDR is detected, this is recorded so that the
* logical map built from DT is validated and can be used
* to override the map created in smp_setup_processor_id().
*/
if
(
hwid
==
mpidr
)
{
i
=
0
;
bootcpu_valid
=
true
;
}
else
{
i
=
cpuidx
++
;
}
tmp_map
[
i
]
=
hwid
;
if
(
cpuidx
>
nr_cpu_ids
)
break
;
}
if
(
WARN
(
!
bootcpu_valid
,
"DT missing boot CPU MPIDR[23:0], "
"fall back to default cpu_logical_map
\n
"
))
return
;
/*
* Since the boot CPU node contains proper data, and all nodes have
* a reg property, the DT CPU list can be considered valid and the
* logical map created in smp_setup_processor_id() can be overridden
*/
for
(
i
=
0
;
i
<
cpuidx
;
i
++
)
{
set_cpu_possible
(
i
,
true
);
cpu_logical_map
(
i
)
=
tmp_map
[
i
];
pr_debug
(
"cpu logical map 0x%x
\n
"
,
cpu_logical_map
(
i
));
}
}
/**
* setup_machine_fdt - Machine setup when an dtb was passed to the kernel
* @dt_phys: physical address of dt blob
...
...
arch/arm/kernel/setup.c
View file @
e38eb34a
...
...
@@ -426,13 +426,14 @@ int __cpu_logical_map[NR_CPUS];
void
__init
smp_setup_processor_id
(
void
)
{
int
i
;
u32
cpu
=
is_smp
()
?
read_cpuid_mpidr
()
&
0xff
:
0
;
u32
mpidr
=
is_smp
()
?
read_cpuid_mpidr
()
&
MPIDR_HWID_BITMASK
:
0
;
u32
cpu
=
MPIDR_AFFINITY_LEVEL
(
mpidr
,
0
);
cpu_logical_map
(
0
)
=
cpu
;
for
(
i
=
1
;
i
<
NR_CPUS
;
++
i
)
for
(
i
=
1
;
i
<
nr_cpu_ids
;
++
i
)
cpu_logical_map
(
i
)
=
i
==
cpu
?
0
:
i
;
printk
(
KERN_INFO
"Booting Linux on physical CPU
%d
\n
"
,
cpu
);
printk
(
KERN_INFO
"Booting Linux on physical CPU
0x%x
\n
"
,
mpidr
);
}
static
void
__init
setup_processor
(
void
)
...
...
@@ -758,6 +759,7 @@ void __init setup_arch(char **cmdline_p)
unflatten_device_tree
();
arm_dt_init_cpu_maps
();
#ifdef CONFIG_SMP
if
(
is_smp
())
{
smp_set_ops
(
mdesc
->
smp
);
...
...
arch/arm/kernel/topology.c
View file @
e38eb34a
...
...
@@ -196,32 +196,7 @@ static inline void parse_dt_topology(void) {}
static
inline
void
update_cpu_power
(
unsigned
int
cpuid
,
unsigned
int
mpidr
)
{}
#endif
/*
* cpu topology management
*/
#define MPIDR_SMP_BITMASK (0x3 << 30)
#define MPIDR_SMP_VALUE (0x2 << 30)
#define MPIDR_MT_BITMASK (0x1 << 24)
/*
* These masks reflect the current use of the affinity levels.
* The affinity level can be up to 16 bits according to ARM ARM
*/
#define MPIDR_HWID_BITMASK 0xFFFFFF
#define MPIDR_LEVEL0_MASK 0x3
#define MPIDR_LEVEL0_SHIFT 0
#define MPIDR_LEVEL1_MASK 0xF
#define MPIDR_LEVEL1_SHIFT 8
#define MPIDR_LEVEL2_MASK 0xFF
#define MPIDR_LEVEL2_SHIFT 16
/*
/*
* cpu topology table
*/
struct
cputopo_arm
cpu_topology
[
NR_CPUS
];
...
...
@@ -282,19 +257,14 @@ void store_cpu_topology(unsigned int cpuid)
if
(
mpidr
&
MPIDR_MT_BITMASK
)
{
/* core performance interdependency */
cpuid_topo
->
thread_id
=
(
mpidr
>>
MPIDR_LEVEL0_SHIFT
)
&
MPIDR_LEVEL0_MASK
;
cpuid_topo
->
core_id
=
(
mpidr
>>
MPIDR_LEVEL1_SHIFT
)
&
MPIDR_LEVEL1_MASK
;
cpuid_topo
->
socket_id
=
(
mpidr
>>
MPIDR_LEVEL2_SHIFT
)
&
MPIDR_LEVEL2_MASK
;
cpuid_topo
->
thread_id
=
MPIDR_AFFINITY_LEVEL
(
mpidr
,
0
);
cpuid_topo
->
core_id
=
MPIDR_AFFINITY_LEVEL
(
mpidr
,
1
);
cpuid_topo
->
socket_id
=
MPIDR_AFFINITY_LEVEL
(
mpidr
,
2
);
}
else
{
/* largely independent cores */
cpuid_topo
->
thread_id
=
-
1
;
cpuid_topo
->
core_id
=
(
mpidr
>>
MPIDR_LEVEL0_SHIFT
)
&
MPIDR_LEVEL0_MASK
;
cpuid_topo
->
socket_id
=
(
mpidr
>>
MPIDR_LEVEL1_SHIFT
)
&
MPIDR_LEVEL1_MASK
;
cpuid_topo
->
core_id
=
MPIDR_AFFINITY_LEVEL
(
mpidr
,
0
);
cpuid_topo
->
socket_id
=
MPIDR_AFFINITY_LEVEL
(
mpidr
,
1
);
}
}
else
{
/*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment