Linux: Activating the first Cpu__linux

Source: Internet
Author: User


Excerpt from: http://blog.csdn.net/yunsongice/article/details/6130032

Return to start_kernel,559 line, Boot_cpu_init function, with Start_kernel in same file:

494static void __init boot_cpu_init (void)

495{

496 int cpu = SMP_PROCESSOR_ID ();

497/* Mark the Boot CPU "present", "online" etc for SMP and up case * *

498 Set_cpu_online (CPU, true);

499 set_cpu_active (CPU, true);

Set_cpu_present (CPU, true);

501 set_cpu_possible (CPU, true);

502}

496 lines, the first time to see smp_processor_id macros. Because the config_debug_preempt is not configured, it is equivalent to calling the macro raw_smp_processor_id, which means that the ID of the current CPU is obtained in the case of SMP. If it is not SMP, then return 0. Then in the case of CONFIG_X86_32_SMP:

#define RAW_SMP_PROCESSOR_ID () (Percpu_read (Cpu_number))

Be sure to note that here Cpu_number 30 lines from ARCH/X86/KERNEL/SETUP_PERCPU.C:

30DEFINE_PER_CPU (int, cpu_number);

31export_per_cpu_symbol (Cpu_number);

This thing is not like the C language global variable, but is defined by two macros. To understand these two macros, you must know the concept of every CPU variable, if it is not clear to the students please check the blog "Per CPU variable" http://blog.csdn.net/yunsongice/archive/2010/05/18/5605239.aspx.

where define_per_cpu from file include/linux/percpu-defs.h:

#define DEFINE_PER_CPU (type, name)/

Define_per_cpu_section (type, Name, "")

The macro statically assigns a per-CPU array with an array named name and struct type. Since we did not set the CONFIG_DEBUG_FORCE_WEAK_PER_CPU compilation option, Define_per_cpu_section is also defined as:

#define Define_per_cpu_section (Type, name, sec)

__pcpu_attrs (sec) Per_cpu_def_attributes/

__typeof__ (type) name

Wherein, the __pcpu_attrs (SEC) is defined in Include/linux/percpu-defs.h:

#define __PCPU_ATTRS (SEC)/

__PERCPU __attribute__ (Section (per_cpu_base_section sec))

Per_cpu_attributes

__PERCPU is a compiler extension type, you can go to see include/linux/compile.h this file, the inside of the __percpu is empty. The passing in the SEC is also empty, per_cpu_attributes is also empty, and the above per_cpu_def_attributes or empty code, may be for future kernel code extension of the bar, so define_per_cpu (int, CPU _number) Expansion is:

__attribute__ ((section (per_cpu_base_section))/

__typeof__ (int) cpu_number

So now just focus on per_cpu_base_section, from Include/asm-generic/percpu.h

#ifdef CONFIG_SMP

#define Per_cpu_base_section ". Data.percpu"

#else

#define PER_CPU_BASE_SECTION ". Data"

#endif

OK, let's introduce some of the GCC extensions, first how to use TypeOf to support some "genericprogramming". GCC supports a technique called type recognition, which uses the typeof (x) keyword to obtain the data type of x. And if you get the data type of a variable in a header file that you want to include in some C file, you need to use the __typeof__ instead of the TypeOf keyword, like here. Finally, here is a cpu_number pointer that declares an int type and points him to the beginning of the. DATA.PERCPU segment.

Of course, we do not have to write the program when the generic programming, so there is no need to do so, but to become a kernel of people, mastering these technologies is necessary. What do you mean by Define_per_cpu_section macros? 147 lines defined in Arch/x86/kernel/percpu-defs.h:

#define EXPORT_PER_CPU_SYMBOL (Var) export_symbol (Var)

Export_symbol is something. Remember when we compiled the kernel with a kallsyms target? This is the place to use. So I said, the kernel of the compilation process is very important, please be sure to master. This object corresponds to the "/proc/kallsyms" file, which corresponds to the kernel symbol table and records the symbol and the memory address where the symbol resides. The module can export symbols to the kernel symbol table using the following macros:

Export_symbol (symbol name);

EXPORT_SYMBOL_GPL (symbol name)

The exported symbols can be used by other modules, but be sure to declare them before use. EXPORT_SYMBOL_GPL () only applies to modules that contain the GPL license. So, Export_symbol (Cpu_number) is the cpu_number variable declaration. Next, let's focus on Percpu_read, a macro from arch/x86/include/asm/percpu.h:

#define Percpu_read (Var) percpu_from_op ("mov", Var, "M" (Var))

See MOV, we know that it may be called assembly language, so this macro calls Percpu_from_op ("mov", Cpu_number, "M" (Cpu_number)), the macro is located in the same file:

164#define percpu_from_op (OP, VAR, constraint)/

165 ({/

166 typeof (Var) pfo_ret__; /

167 switch (sizeof (VAR)) {/

Case 1:/

169 ASM (OP "B" __percpu_arg (1) ",%0"/

170: "=q" (pfo_ret__)/

171:constraint); /

172 break; /

173 Case 2:/

174 ASM (OP "w" __percpu_arg (1) ",%0"/

175: "=r" (pfo_ret__)/

176:constraint); /

177 break; /

178 Case 4:/

179 ASM (OP "L" __percpu_arg (1) ",%0"/

180: "=r" (pfo_ret__)/

181:constraint); /

a break; /

183 Case 8:/

184 ASM (OP "q" __percpu_arg (1) ",%0"/

185: "=r" (pfo_ret__)/

186:constraint); /

187 break; /

188 Default: __bad_percpu_size (); /

189}/

190 pfo_ret__; /

191})

Of course, in order to get the CPU number, cpu_number with a byte is enough, so the above code translation is:

ASM ("Movb" __percpu_arg (1) ",%0"/

: "=q" (pfo_ret__)/

: constraint);

Of these, __percpu_arg (1) is defined as:

#ifdef CONFIG_SMP

#define __PERCPU_ARG (x) "Percent%" __stringify (__percpu_seg) ":%P" #x

#ifdef config_x86_64

#define __PERCPU_SEG GS

#define __PERCPU_MOV_OP MOVQ

#else

#define __PERCPU_SEG FS

#define __PERCPU_MOV_OP MOVL

#endif

So __percpu_arg (x) translation is:

"% percent" __stringify (FS) ":%P" #x

Please note that this is the first time you have encountered such a definition, unlike our traditional C language macros. Yes, here is to learn new knowledge, first talk about # and # #的知识.

In the C language macro, #的功能是将其后面的宏参数进行字符串化操作 (stringfication), simply by adding a double quotation mark around the macro variable that it references by replacing it. such as __percpu_arg macros:

#define __PERCPU_ARG (x) "Percent%" __stringify (__percpu_seg) ":%P" #x

And X, we're passing in the 1;__percpu_seg, we're passing in FS, so __percpu_arg expands:

% percent "__stringify (FS)":%P "" 1 "

and # #, although there is no use, but I still talk about, for you to expand the C language knowledge. # #被称为连接符 (concatenator), used to connect two token to a token. Note that the object being connected here is token, not necessarily a macro variable. Like what:

#define Link_multiple (a,b,c,d) a# #_ # #b # #_ # #c # #_ # #d

typedef struct RECORD_TYPE link_multiple (name,company,position,salary);

Here the statement expands to:

typedef struct RECORD_TYPE name_company_position_salary;

Another new knowledge, variable parameter macros, was defined in the ISO C standard in 1999, just ten years ago. We see a __stringify macro here, which is defined as this:

#define __STRINGIFY (x ...) __stringify_1 (x)

Which ... As a variable parameter, what does it mean. This is the macro. In addition to X, there are several additional parameters. In addition, if a variable parameter macro is used, the variable parameter x may expand to multiple parameters, for example, it can also be defined as:

#define __STRINGIFY (...) My__stringify (y,z) 0

However, if the parameter name x is specified, the latter must contain an x:

#define __STRINGIFY (x ...) my__stringify (x,y,z)

So I'm going to ask, what if I define the form of the three parameters above, but only two arguments. such as executing a __stringify (A,B) statement, there will be no error. Of course I will. Since it's a macro with variable parameters, it's right to pass in an empty parameter, except you have to have the extra comma, which is __stringify (a,b).

But there's one thing that GCC can do to avoid this "bug", which is #符号. If we define it as:

#define __STRINGIFY (x ...) my__stringify (# #x, y,z)

At this point, # #这个连接符号充当的作用就是当x为空的时候, to eliminate the previous comma, so there will not be the above bug.

So macros:

#define __STRINGIFY_1 (x ...) #x

We can see it, right?

So __percpu_arg (1) finally translated is:

"% percent" "fs:%p" "1"

So the above assembly code is translated:

ASM ("Movb%%fs:%p1,%0"/

: "=q" (pfo_ret__)/

: "M" (Var));

Where pfo_ret__ is the output part%0,q, which represents one of the registers eax, EBX, ecx, or edx, and the variable pfo_ret__ is stored in this register. var is the temporary assembler variable Cpu_number that we built just now, as input part%1.

Remember the "Load Global/Interrupt Descriptor Chart" in the __kernel_percpu section of the selection of the child assigned to the FS, yes, Fs:cpu_number is currently stored in the __KERNEL_PERCPU section of the Cpu_number offset in memory, Finally return the result to pfo_ret__. So the final result of this macro is the value of pfo_ret__, which returns the number of the CPU and assigns it to the internal variable CPU of the Boot_cpu_init function.

So how much is this offset cpu_number? The crowd looked for him 1100 degrees, looking back, this offset in the generated vmlinux.lds file of 504 lines was discovered by me:

__per_cpu_load =.; . data.percpu 0

Yes, just now. Data.percpu is compiled into 0, so the internal CPU value is 0. Why do I make this part so detailed, because this part of the content contains a lot of kernel code details, later encountered the same problem we will follow this method to analyze, extrapolate. The following four functions Set_cpu_online, set_cpu_active, set_cpu_present and set_cpu_possible I do not want to say more, is to activate the current CPU Cpu_present_ Bits in the four logo bit online, active, present and possible, interested students can be learned through the above methods to analyze the details.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.