x86_64, i386: interrupt dispatch changes
PATCH 1/1 x86_64, i386: interrupt dispatch changes
Hi all,
An x86 processor handles an interrupt (from an external source, software generated or due to an exception), depending on the contents if the IDT. Normally the IDT contains mostly interrupt gates. Linux points each interrupt gate to a unique function. Some are specific to some task (handling traps, IPI's, ...), the others are stubs that push the interrupt number to the stack and jump to 'common_interrupt'.
This patch removes the need for the stubs.
An interrupt gate contains a FAR pointer to the interrupt handler, meaning that the code segment of the interrupt handler is also reloaded. Instead of pointing each (non- specific) interrupt gate to a unique handler, we set a unique code segment and use a common handler. When the handler finishes the code segment is restored to the 'normal'/previous one.
In order to have a unique code segment for each interrupt vector, the GDT is extended to 512 entries (1 full page), and the last half of the page describes identical code segments (identical, except for the number in the cs register), which are refered to by the 256 interrupt gates.
In this version, even the specialized handlers get run with their code segment switched. This is not necessary, but I like the fact that in a register dump one can now see from the code segment that the code is ran due to a (hard) interrupt. The exception I made is the int 0x80 (syscall), which runs with the normal kernel code segment.
Concluding: changing interrupt handling to this way removes quite a bit of source code. It also removes the need for the interrupt stubs and, on i386, pointers to them. This saves a few kilobytes of code. The page reserved for the GDT is now fully used. The cs register indicating directly that code is executed on behalf of a (hardware) interrupt is a nice debugging aid. This way of handling interrupts also leads to cleaner code: this patch already gets rid of some 'ugly' macro magic in entry_32.S and irqinit_64.c.
More cleanup is certainly possible, but I have tried to keep the changes local and small. If switching code segments is too expensive for some paths, that can be fixed by not doing that ;).
I'ld welcome some numbers on a few benchmarks on real hardware (I only tested on qemu: debian runs without noticable differences before/after this patch).
Greetings,
Alexander
P.S. Just in case someone thinks this is a great idea and testing and benchmarking goes well...
arch/x86/include/asm/desc.h | 24 +++++----- arch/x86/include/asm/segment.h | 14 +----- arch/x86/kernel/cpu/common.c | 3 + arch/x86/kernel/entry_32.S | 33 ++++---------- arch/x86/kernel/head64.c | 4 -- arch/x86/kernel/head_32.S | 37 +++++---------- arch/x86/kernel/head_64.S | 18 ++----- arch/x86/kernel/irqinit_32.c | 4 +- arch/x86/kernel/irqinit_64.c | 96 +++++++--------------------------------- arch/x86/kernel/traps.c | 4 +- 10 files changed, 64 insertions(+), 173 deletions(-)
arch/x86/include/asm/desc.h +12 -12
@@ -50,7 +50,7 @@ static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, unsigned dpl, unsigned ist, unsigned seg) { gate->offset_low = PTR_LOW(func); - gate->segment = __KERNEL_CS; + gate->segment = seg; gate->ist = ist; gate->p =1 ; gate->dpl = dpl;
@@ -317,7 +317,7 @@ static inline void _set_gate(int gate, unsigned type, void *addr,static inline void set_intr_gate (unsigned int n,void *addr) {BUG_ON ((unsigned )n >0xFF ); -_set_gate (n,GATE_INTERRUPT , addr,0 ,0 , __KERNEL_CS); +_set_gate (n,GATE_INTERRUPT , addr,0 ,0 , (256 + n) *8 ); }#define SYS_VECTOR_FREE 0
@@ -348,37 +348,37 @@ static inline void alloc_intr_gate(unsigned int n, void *addr)static inline void set_system_intr_gate (unsigned int n,void *addr) {BUG_ON ((unsigned )n >0xFF ); -_set_gate (n,GATE_INTERRUPT , addr,0x3 ,0 , __KERNEL_CS); +_set_gate (n,GATE_INTERRUPT , addr,0x3 ,0 , (256 + n) *8 ); } -static inline void set_system_trap_gate (unsigned int n,void *addr) +static inline void set_system_gate (unsigned int n,void *addr) {BUG_ON ((unsigned )n >0xFF ); +#ifdef CONFIG_X86_64 +_set_gate (n,GATE_INTERRUPT , addr,0x3 ,0 , __KERNEL_CS); +#else _set_gate (n,GATE_TRAP , addr,0x3 ,0 , __KERNEL_CS); +#endif } -static inline void set_trap_gate (unsigned int n,void *addr) -{ -BUG_ON ((unsigned )n >0xFF ); -_set_gate (n,GATE_TRAP , addr,0 ,0 , __KERNEL_CS); -} - +#ifdef CONFIG_X86_32 static inline void set_task_gate (unsigned int n,unsigned int gdt_entry) {BUG_ON ((unsigned )n >0xFF );_set_gate (n,GATE_TASK , (void *)0 ,0 ,0 , (gdt_entry<<3 )); } +#endif static inline void set_intr_gate_ist (int n,void *addr,unsigned ist) {BUG_ON ((unsigned )n >0xFF ); -_set_gate (n,GATE_INTERRUPT , addr,0 , ist, __KERNEL_CS); +_set_gate (n,GATE_INTERRUPT , addr,0 , ist, (256 + n) *8 ); }static inline void set_system_intr_gate_ist (int n,void *addr,unsigned ist) {BUG_ON ((unsigned )n >0xFF ); -_set_gate (n,GATE_INTERRUPT , addr,0x3 , ist, __KERNEL_CS); +_set_gate (n,GATE_INTERRUPT , addr,0x3 , ist, (256 + n) *8 ); }#else
arch/x86/include/asm/segment.h +1 -13
@@ -97,11 +97,6 @@#define GDT_ENTRY_DOUBLEFAULT_TSS 31 -/* -* The GDT has 32 entries -*/ -#define GDT_ENTRIES 32 -/* The PnP BIOS entries in the GDT */ #define GDT_ENTRY_PNPBIOS_CS32 (GDT_ENTRY_PNPBIOS_BASE + 0)#define GDT_ENTRY_PNPBIOS_CS16 (GDT_ENTRY_PNPBIOS_BASE + 1)
@@ -171,8 +166,6 @@#define GS_TLS_SEL ((GDT_ENTRY_TLS_MIN+GS_TLS)*8 + 3)#define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3) -#define GDT_ENTRIES 16 -#endif #define __KERNEL_CS (GDT_ENTRY_KERNEL_CS * 8)
@@ -195,15 +188,10 @@#define SEGMENT_TI_MASK 0x4#define IDT_ENTRIES 256 +#define GDT_ENTRIES 512#define NUM_EXCEPTION_VECTORS 32#define GDT_SIZE (GDT_ENTRIES * 8)#define GDT_ENTRY_TLS_ENTRIES 3#define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8) -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ -extern const char early_idt_handlers[NUM_EXCEPTION_VECTORS ][10 ]; -#endif -#endif -#endif /* _ASM_X86_SEGMENT_H */
arch/x86/kernel/cpu/common.c +3 -0
@@ -55,6 +55,7 @@ DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } }, [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, + [256 ... 511] = { { { 0x0000ffff, 0x00af9b00 } } } } }; #else DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = {
@@ -90,6 +91,8 @@ DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, + + [256 ... 511] = { { { 0x0000ffff, 0x00cf9a00 } } } } };#endif EXPORT_PER_CPU_SYMBOL_GPL (gdt_page);
arch/x86/kernel/entry_32.S +10 -23
@@ -622,31 +622,18 @@ END(syscall_badsys) * Build the entry stubs and pointer table with * some assembler magic. */ -.section .rodata,"a" -ENTRY(interrupt) -.text - -ENTRY(irq_entries_start) +.p2align +ENTRY(maininterrupt) RING0_INT_FRAME -vector=0 -.rept NR_VECTORS - ALIGN - .if vector - CFI_ADJUST_CFA_OFFSET -4 - .endif -1: pushl $~(vector) - CFI_ADJUST_CFA_OFFSET 4 + push %eax + push %eax + mov %cs,%eax + shr $3,%eax + and $0xff,%eax + not %eax + mov %eax,4(%esp) + pop %eax jmp common_interrupt - .previous - .long 1b - .text -vector=vector+1 -.endr -END(irq_entries_start) - -.previous -END(interrupt) -.previous /* * the CPU automatically disables interrupts when executing an IRQ vector,
arch/x86/kernel/head64.c +0 -4
@@ -100,11 +100,7 @@ void __init x86_64_start_kernel(char * real_mode_data)cleanup_highmap ();for (i =0 ; i <NUM_EXCEPTION_VECTORS ; i++) { -#ifdef CONFIG_EARLY_PRINTK -set_intr_gate (i, &early_idt_handlers[i]); -#else set_intr_gate (i, early_idt_handler); -#endif }load_idt ((const struct desc_ptr *)&idt_descr);
arch/x86/kernel/head_32.S +13 -24
@@ -486,7 +486,7 @@ check_x87: */ setup_idt: lea ignore_int,%edx - movl $(__KERNEL_CS << 16),%eax + movl $((256 * 8) << 16),%eax /* cs = (256 + irq_nr) * 8 */ movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
@@ -496,12 +496,13 @@ rp_sidt: movl %eax,(%edi) movl %edx,4(%edi) addl $8,%edi + addl $(8 << 16),%eax /* cs = (256 + irq_nr) * 8 */ dec %ecx jne rp_sidt .macro set_early_handler handler,trapno lea \handler,%edx - movl $(__KERNEL_CS << 16),%eax + movl $(((256 + \trapno) * 8) << 16),%eax movw %dx,%ax movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ lea idt_table,%edi
@@ -509,30 +510,15 @@ rp_sidt: movl %edx,8*\trapno+4(%edi) .endm - set_early_handler handler=early_divide_err,trapno=0 - set_early_handler handler=early_illegal_opcode,trapno=6 - set_early_handler handler=early_protection_fault,trapno=13 - set_early_handler handler=early_page_fault,trapno=14 + set_early_handler handler=early_fault_fake_errorcode,trapno=0 + set_early_handler handler=early_fault_fake_errorcode,trapno=6 + set_early_handler handler=early_fault,trapno=13 + set_early_handler handler=early_fault,trapno=14 ret -early_divide_err: - xor %edx,%edx - pushl $0 /* fake errcode */ - jmp early_fault - -early_illegal_opcode: - movl $6,%edx - pushl $0 /* fake errcode */ - jmp early_fault - -early_protection_fault: - movl $13,%edx - jmp early_fault - -early_page_fault: - movl $14,%edx - jmp early_fault +early_fault_fake_errorcode: + pushl $0 early_fault: cld
@@ -546,7 +532,10 @@ early_fault: incl early_recursion_flag movl %cr2,%eax pushl %eax - pushl %edx /* trapno */ + mov %cs, %eax + shr $3, %eax + and $0xff, %eax + pushl %eax /* trapno */ pushl $fault_msg #ifdef CONFIG_EARLY_PRINTK call early_printk
arch/x86/kernel/head_64.S +5 -13
@@ -267,17 +267,6 @@ bad_address: jmp bad_address .section ".init.text","ax" -#ifdef CONFIG_EARLY_PRINTK - .globl early_idt_handlers -early_idt_handlers: - i = 0 - .rept NUM_EXCEPTION_VECTORS - movl $i, %esi - jmp early_idt_handler - i = i + 1 - .endr -#endif - ENTRY(early_idt_handler) #ifdef CONFIG_EARLY_PRINTK cmpl $2,early_recursion_flag(%rip)
@@ -286,7 +275,9 @@ ENTRY(early_idt_handler) GET_CR2_INTO_RCX movq %rcx,%r9 xorl %r8d,%r8d # zero for error code - movl %esi,%ecx # get vector number + mov %cs, %ecx + shr $3, %ecx + and $0xff, %ecx # get vector number from CS # Test %ecx against mask of vectors that push error code. cmpl $31,%ecx ja 0f
@@ -295,7 +286,8 @@ ENTRY(early_idt_handler) testl $0x27d00,%eax je 0f popq %r8 # get error code -0: movq 0(%rsp),%rcx # get ip +0: mov %ecx, %esi # vector number + movq 0(%rsp),%rcx # get ip movq 8(%rsp),%rdx # get cs xorl %eax,%eax leaq early_idt_msg(%rip),%rdi
arch/x86/kernel/irqinit_32.c +2 -2
@@ -21,7 +21,7 @@#include <asm/arch_hooks.h> #include <asm/i8259.h> - +void maininterrupt (void );/* * Note that on a 486, we don't want to do a SIGFPE on an irq13
@@ -129,7 +129,7 @@ void __init native_init_IRQ(void)for (i =FIRST_EXTERNAL_VECTOR ; i <NR_VECTORS ; i++) {/* SYSCALL_VECTOR was reserved in trap_init. */ if (i !=SYSCALL_VECTOR ) -set_intr_gate (i, interrupt[i]); +set_intr_gate (i, maininterrupt); }
arch/x86/kernel/irqinit_64.c +16 -80
109 lines not on this page · raw message
arch/x86/kernel/traps.c +2 -2
@@ -996,7 +996,7 @@ void __init trap_init(void)set_intr_gate (19 , &simd_coprocessor_error);#ifdef CONFIG_IA32_EMULATION -set_system_intr_gate (IA32_SYSCALL_VECTOR , ia32_syscall); +set_system_gate (IA32_SYSCALL_VECTOR , ia32_syscall);#endif #ifdef CONFIG_X86_32
@@ -1012,7 +1012,7 @@ void __init trap_init(void)printk ("done.\n" ); } -set_system_trap_gate (SYSCALL_VECTOR , &system_call); +set_system_gate (SYSCALL_VECTOR , &system_call);/* Reserve all the builtin and the syscall vector: */ for (i =0 ; i <FIRST_EXTERNAL_VECTOR ; i++)
Quoted 11 lines · Alexander van Heukelum
Hi all,
An x86 processor handles an interrupt (from an external source, software generated or due to an exception), depending on the contents if the IDT. Normally the IDT contains mostly interrupt gates. Linux points each interrupt gate to a unique function. Some are specific to some task (handling traps, IPI's, ...), the others are stubs that push the interrupt number to the stack and jump to '
common_interrupt'.This patch removes the need for the stubs.
hm, the cost would be this new code:
Quoted 10 lines
+.p2align
arch/x86/kernel/entry_32.S +1
-7+ENTRY(maininterrupt) RING0_INT_FRAME -vector=0 -.rept NR_VECTORS - ALIGN - .if vector - CFI_ADJUST_CFA_OFFSET -4 - .endif -1: pushl $~(vector)
arch/x86/kernel/entry_32.S END(syscall_badsys) · line 636
Quoted 10 lines
arch/x86/kernel/entry_32.S +8
-1- CFI_ADJUST_CFA_OFFSET 4 + push %eax + push %eax + mov %cs,%eax + shr $3,%eax + and $0xff,%eax + not %eax + mov %eax,4(%esp) + pop %eax jmp common_interrupt
.. which we were able to avoid before. A couple of segment register accesses, shifts, etc to calculate the vector - each of which can be quite costly (especially the segment register access - this is a relatively rare instruction pattern).
I'm not unconvicable, but we need to be conservative here: could you try to measure the full before/after cost of IRQ entry, to the cycle level? I'm curious what the performance impact is.
Also, this makes life probably a bit harder for Xen, which assumes that the GDT of the guest OS is small-ish. (Jeremy Cc:-ed)
Ingo
Quoted 34 lines · Ingo Molnar
Quoted 11 lines · Alexander van Heukelum
Hi all,
An x86 processor handles an interrupt (from an external source, software generated or due to an exception), depending on the contents if the IDT. Normally the IDT contains mostly interrupt gates. Linux points each interrupt gate to a unique function. Some are specific to some task (handling traps, IPI's, ...), the others are stubs that push the interrupt number to the stack and jump to '
common_interrupt'.This patch removes the need for the stubs.
hm, the cost would be this new code:
Quoted 17 lines
+.p2align
arch/x86/kernel/entry_32.S +7
-8+ENTRY(maininterrupt) RING0_INT_FRAME -vector=0 -.rept NR_VECTORS - ALIGN - .if vector - CFI_ADJUST_CFA_OFFSET -4 - .endif -1: pushl $~(vector) - CFI_ADJUST_CFA_OFFSET 4 + push %eax + push %eax + mov %cs,%eax + shr $3,%eax + and $0xff,%eax + not %eax
Quoted 8 lines
arch/x86/kernel/entry_32.S END(syscall_badsys) · line 636
Quoted 3 lines
arch/x86/kernel/entry_32.S +2
-0+ mov %eax,4(%esp) + pop %eax jmp common_interrupt.. which we were able to avoid before. A couple of segment register accesses, shifts, etc to calculate the vector - each of which can be quite costly (especially the segment register access - this is a relatively rare instruction pattern).
The way it is written now is just so I did not have to change common_interrupt (to keep changes small). All those accesses so close together will cost some cycles, but much can be avoided if it is integrated. If the precise content of the stack can be changed, this could be as simple as "push %cs". Even that can be delayed, because the content of the cs register will still be there.
Note that the specialized interrupts (including page fault, etc.) will not go via this path. As far as I understand now, it is only the interrupts from external devices that normally go via common_interrupt. There I think the overhead is really tiny compared to the rest of the handling of the interrupt.
Quoted 6 lines
I'm not unconvicable, but we need to be conservative here: could you try to measure the full before/after cost of IRQ entry, to the cycle level? I'm curious what the performance impact is.
Also, this makes life probably a bit harder for Xen, which assumes that the GDT of the guest OS is small-ish. (Jeremy Cc:-ed)
I already had [email protected] for exactly this reason ;).
Greetings,
Alexander
Quoted 1 line
Ingo
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - A no graphics, no pop-ups email service
Quoted 51 lines · Alexander van Heukelum
Quoted 34 lines · Ingo Molnar
Quoted 11 lines · Alexander van Heukelum
Hi all,
An x86 processor handles an interrupt (from an external source, software generated or due to an exception), depending on the contents if the IDT. Normally the IDT contains mostly interrupt gates. Linux points each interrupt gate to a unique function. Some are specific to some task (handling traps, IPI's, ...), the others are stubs that push the interrupt number to the stack and jump to '
common_interrupt'.This patch removes the need for the stubs.
hm, the cost would be this new code:
Quoted 17 lines
+.p2align
arch/x86/kernel/entry_32.S +7
-8+ENTRY(maininterrupt) RING0_INT_FRAME -vector=0 -.rept NR_VECTORS - ALIGN - .if vector - CFI_ADJUST_CFA_OFFSET -4 - .endif -1: pushl $~(vector) - CFI_ADJUST_CFA_OFFSET 4 + push %eax + push %eax + mov %cs,%eax + shr $3,%eax + and $0xff,%eax + not %eaxQuoted 8 lines
arch/x86/kernel/entry_32.S END(syscall_badsys) · line 636
Quoted 3 lines
arch/x86/kernel/entry_32.S +2
-0+ mov %eax,4(%esp) + pop %eax jmp common_interrupt.. which we were able to avoid before. A couple of segment register accesses, shifts, etc to calculate the vector - each of which can be quite costly (especially the segment register access - this is a relatively rare instruction pattern).
The way it is written now is just so I did not have to change
common_interrupt(to keep changes small). All those accesses so close together will cost some cycles, but much can be avoided if it is integrated. If the precise content of the stack can be changed, this could be as simple as "push %cs". Even that can be delayed, because the content of the cs register will still be there.
Quoted 5 lines
Note that the specialized interrupts (including page fault, etc.) will not go via this path. As far as I understand now, it is only the interrupts from external devices that normally go via
common_interrupt. There I think the overhead is really tiny compared to the rest of the handling of the interrupt.
no complaints from me about the cleanup/simplification effect - that's really great. To make the reasoning all iron-clad please post timings of "push %cs" costs measured via RDTSC or so - can be done in user-space as well. (you can simulate the entry+exit sequence in user-space as well and prove that the overhead is near zero.) In the end it could all even be faster (perhaps), besides smaller.
( another advantage is that the 6 bytes GDT descriptor is more
compressed and hence uses up less L1/L2 cache footprint than the larger (~7 byte) trampolines we have at the moment. )
plus it's possible to observe the typical cost of irqs from user-space as well: run a task on a single CPU and save away all the RDTSC deltas that are larger than ~10 cycles - these will be the IRQ entry costs. Print out these deltas after 60 seconds of runtime (or something like that), and look at the histogram.
Ingo
Quoted 60 lines · Ingo Molnar
Quoted 51 lines · Alexander van Heukelum
Quoted 34 lines · Ingo Molnar
Quoted 11 lines · Alexander van Heukelum
Hi all,
An x86 processor handles an interrupt (from an external source, software generated or due to an exception), depending on the contents if the IDT. Normally the IDT contains mostly interrupt gates. Linux points each interrupt gate to a unique function. Some are specific to some task (handling traps, IPI's, ...), the others are stubs that push the interrupt number to the stack and jump to '
common_interrupt'.This patch removes the need for the stubs.
hm, the cost would be this new code:
Quoted 17 lines
+.p2align
arch/x86/kernel/entry_32.S +7
-8+ENTRY(maininterrupt) RING0_INT_FRAME -vector=0 -.rept NR_VECTORS - ALIGN - .if vector - CFI_ADJUST_CFA_OFFSET -4 - .endif -1: pushl $~(vector) - CFI_ADJUST_CFA_OFFSET 4 + push %eax + push %eax + mov %cs,%eax + shr $3,%eax + and $0xff,%eax + not %eaxQuoted 8 lines
arch/x86/kernel/entry_32.S END(syscall_badsys) · line 636
Quoted 3 lines
arch/x86/kernel/entry_32.S +2
-0+ mov %eax,4(%esp) + pop %eax jmp common_interrupt.. which we were able to avoid before. A couple of segment register accesses, shifts, etc to calculate the vector - each of which can be quite costly (especially the segment register access - this is a relatively rare instruction pattern).
The way it is written now is just so I did not have to change
common_interrupt(to keep changes small). All those accesses so close together will cost some cycles, but much can be avoided if it is integrated. If the precise content of the stack can be changed, this could be as simple as "push %cs". Even that can be delayed, because the content of the cs register will still be there.Quoted 5 lines
Note that the specialized interrupts (including page fault, etc.) will not go via this path. As far as I understand now, it is only the interrupts from external devices that normally go via
common_interrupt. There I think the overhead is really tiny compared to the rest of the handling of the interrupt.
Quoted 6 lines
no complaints from me about the cleanup/simplification effect - that's really great. To make the reasoning all iron-clad please post timings of "push %cs" costs measured via RDTSC or so - can be done in user-space as well. (you can simulate the entry+exit sequence in user-space as well and prove that the overhead is near zero.) In the end it could all even be faster (perhaps), besides smaller.
I did some timings using the little program below (32-bit only), doing 1024 times the same sequence. TEST1 is just pushing a constant onto the stack; TEST2 is pushing the cs register; TEST3 is the sequence from the patch to extract the vector number from the cs register.
Opteron (cycles): 1024 / 1157 / 3527
Xeon E5345 (cycles): 1092 / 1085 / 6622
Athlon XP (cycles): 1028 / 1166 / 5192
I'ld say that the cost of the push %cs itself is negligible.
Quoted 3 lines
( another advantage is that the 6 bytes GDT descriptor is more
compressed and hence uses up less L1/L2 cache footprint than the larger (~7 byte) trampolines we have at the moment. )
A GDT descriptor has to be read and processed anyhow... It might just not be in cache. But at least it is aligned. The trampolines are 7 bytes (irq#<128) or 10 bytes (irq#>127) on i386 and x86_64. And one is data, and the other is code, which might also cause different behaviour. It's just a bit too complicated to decide by just reasoning about it ;).
Quoted 5 lines
plus it's possible to observe the typical cost of irqs from user-space as well: run a task on a single CPU and save away all the RDTSC deltas that are larger than ~10 cycles - these will be the IRQ entry costs. Print out these deltas after 60 seconds of runtime (or something like that), and look at the histogram.
I'll see if I can do that. Maybe in a few days...
Thanks,
Alexander
Quoted 1 line
Ingo
#include <stdio.h>
#include <stdlib.h>
#define TEST 3
int main(void)
{
int i, ticks[1024];
for (i=0; i<(sizeof(ticks)/sizeof(*ticks)); i++) {
asm volatile (
"push %%edx\n\t"
"push %%ecx\n\t"
"rdtsc\n\t"
"mov %%eax,%%ecx\n\t"
".rept 1024\n\t"
#if TEST==1
"push $-255\n\t"
#endif
#if TEST==2
"push %%cs\n\t"
#endif
#if TEST==3
"push %%eax\n\t"
"push %%eax\n\t"
"mov %%cs,%%eax\n\t"
"shr $3,%%eax\n\t"
"and $0xff,%%eax\n\t"
"not %%eax\n\t"
"mov %%eax,4(%%esp)\n\t"
"pop %%eax\n\t"
#endif
".endr\n\t"
"rdtsc\n\t"
".rept 1024\n\t"
"pop %%edx\n\t"
".endr\n\t"
"sub %%ecx,%%eax\n\t"
"pop %%ecx\n\t"
"pop %%edx"
: "=a" (ticks[i]) );
}
for (i=0; i<(sizeof(ticks)/sizeof(*ticks)); i++) {
printf("%i\n", ticks[i]);
}
}Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - A fast, anti-spam email service.
[Alexander van Heukelum - Tue, Nov 04, 2008 at 05:23:09PM +0100]
...
| | I did some timings using the little program below (32-bit only), doing | 1024 times the same sequence. TEST1 is just pushing a constant onto | the stack; TEST2 is pushing the cs register; TEST3 is the sequence | from the patch to extract the vector number from the cs register. | | Opteron (cycles): 1024 / 1157 / 3527 | Xeon E5345 (cycles): 1092 / 1085 / 6622 | Athlon XP (cycles): 1028 / 1166 / 5192
Xeon is defenitely out of luck :-)
| | I'ld say that the cost of the push %cs itself is negligible. | | > ( another advantage is that the 6 bytes GDT descriptor is more | > compressed and hence uses up less L1/L2 cache footprint than the | > larger (~7 byte) trampolines we have at the moment. ) | | A GDT descriptor has to be read and processed anyhow... It might | just not be in cache. But at least it is aligned. The trampolines | are 7 bytes (irq#<128) or 10 bytes (irq#>127) on i386 and x86_64. | And one is data, and the other is code, which might also cause | different behaviour. It's just a bit too complicated to decide by | just reasoning about it ;). | | > plus it's possible to observe the typical cost of irqs from user-space | > as well: run a task on a single CPU and save away all the RDTSC deltas | > that are larger than ~10 cycles - these will be the IRQ entry costs. | > Print out these deltas after 60 seconds of runtime (or something like | > that), and look at the histogram. | | I'll see if I can do that. Maybe in a few days... | | Thanks, | Alexander | | > Ingo
...
- Cyrill -
Quoted 12 lines · Cyrill Gorcunov
[Alexander van Heukelum - Tue, Nov 04, 2008 at 05:23:09PM +0100]
...| | I did some timings using the little program below (32-bit only), doing | 1024 times the same sequence. TEST1 is just pushing a constant onto | the stack; TEST2 is pushing the cs register; TEST3 is the sequence | from the patch to extract the vector number from the cs register. | | Opteron (cycles): 1024 / 1157 / 3527 | Xeon E5345 (cycles): 1092 / 1085 / 6622 | Athlon XP (cycles): 1028 / 1166 / 5192
Quoted 1 line
Xeon is defenitely out of luck :-)
it's still OK - i.e. no outrageous showstopper overhead anywhere in that instruction sequence. The total round-trip overhead is what will matter most.
Ingo
[Ingo Molnar - Tue, Nov 04, 2008 at 05:58:11PM +0100]
| | * Cyrill Gorcunov <[email protected]> wrote: | | > [Alexander van Heukelum - Tue, Nov 04, 2008 at 05:23:09PM +0100] | > ... | > | | > | I did some timings using the little program below (32-bit only), doing | > | 1024 times the same sequence. TEST1 is just pushing a constant onto | > | the stack; TEST2 is pushing the cs register; TEST3 is the sequence | > | from the patch to extract the vector number from the cs register. | > | | > | Opteron (cycles): 1024 / 1157 / 3527 | > | Xeon E5345 (cycles): 1092 / 1085 / 6622 | > | Athlon XP (cycles): 1028 / 1166 / 5192 | > | > Xeon is defenitely out of luck :-) | | it's still OK - i.e. no outrageous showstopper overhead anywhere in | that instruction sequence. The total round-trip overhead is what will | matter most. | | Ingo |
Don't get me wrong please, I really like what Alexander have done! But frankly six time slower is a bit scarying me.
- Cyrill -
Quoted 26 lines · Cyrill Gorcunov
[Ingo Molnar - Tue, Nov 04, 2008 at 05:58:11PM +0100]
| | * Cyrill Gorcunov <[email protected]> wrote: | | > [Alexander van Heukelum - Tue, Nov 04, 2008 at 05:23:09PM +0100] | > ... | > | | > | I did some timings using the little program below (32-bit only), doing | > | 1024 times the same sequence. TEST1 is just pushing a constant onto | > | the stack; TEST2 is pushing the cs register; TEST3 is the sequence | > | from the patch to extract the vector number from the cs register. | > | | > | Opteron (cycles): 1024 / 1157 / 3527 | > | Xeon E5345 (cycles): 1092 / 1085 / 6622 | > | Athlon XP (cycles): 1028 / 1166 / 5192 | > | > Xeon is defenitely out of luck :-) | | it's still OK - i.e. no outrageous showstopper overhead anywhere in | that instruction sequence. The total round-trip overhead is what will | matter most. | | Ingo |
Quoted 2 lines
Don't get me wrong please, I really like what Alexander have done! But frankly six time slower is a bit scarying me.
Thanks again ;). Now it _is_ six times slower to do this tiny piece of code... But please keep in mind all the activity that follows to save the current data segment registers (the stack segment and code segment are saved automatically), the general purpose registers and to load most of the data segments with kernel-space values. And looking at it now... do_IRQ is also not exactly trivial.
Also, I kept the information that is saved on the stack exactly the same. If this is not a requirement, "push %cs" is what is left of this expensive (6 cycle!) sequence. Even that could be unnecessary if the stack layout can be changed... But I'ld like to consider that separately.
Greetings,
Alexander
Quoted 1 line
- Cyrill -
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - A no graphics, no pop-ups email service
Quoted 13 lines · Alexander van Heukelum
Quoted 13 lines
| > | Opteron (cycles): 1024 / 1157 / 3527 | > | Xeon E5345 (cycles): 1092 / 1085 / 6622 | > | Athlon XP (cycles): 1028 / 1166 / 5192 | > | > Xeon is defenitely out of luck :-) | | it's still OK - i.e. no outrageous showstopper overhead anywhere in | that instruction sequence. The total round-trip overhead is what will | matter most. | | Ingo |
Quoted 2 lines
Quoted 2 lines
Don't get me wrong please, I really like what Alexander have done! But frankly six time slower is a bit scarying me.
the cost is 6 cycles instead of 1 cycles. In a codepath that takes thousands of cycles and is often cache-limited.
Quoted 7 lines
Thanks again ;). Now it _is_ six times slower to do this tiny piece of code... But please keep in mind all the activity that follows to save the current data segment registers (the stack segment and code segment are saved automatically), the general purpose registers and to load most of the data segments with kernel-space values. And looking at it now...
do_IRQis also not exactly trivial.
Quoted 5 lines
Also, I kept the information that is saved on the stack exactly the same. If this is not a requirement, "push %cs" is what is left of this expensive (6 cycle!) sequence. Even that could be unnecessary if the stack layout can be changed... But I'ld like to consider that separately.
we really want to keep the stack frame consistent between all the context types. We can do things like return-to-userspace-from-irq or schedule-from-irq-initiated-event, etc. - so crossing between these context frames has to be standard and straightforward.
Ingo
Quoted 4 lines · Ingo Molnar
( another advantage is that the 6 bytes GDT descriptor is more
compressed and hence uses up less L1/L2 cache footprint than the larger (~7 byte) trampolines we have at the moment. )
Also its D cache rather than I cache, which is generally more plentiful. However, I think the cost of GDT cache misses on exception latency is something that we've largely overlooked, and this will make it a bigger factor (vs cache misses on the actual exception handler code itself, which should be reduced).
J
H. Peter Anvin
reviewerQuoted 6 lines · Jeremy Fitzhardinge
Quoted 4 lines · Ingo Molnar
( another advantage is that the 6 bytes GDT descriptor is more compressed and hence uses up less L1/L2 cache footprint than the larger (~7 byte) trampolines we have at the moment. )
Quoted 6 lines
Also its D cache rather than I cache, which is generally more plentiful. However, I think the cost of GDT cache misses on exception latency is something that we've largely overlooked, and this will make it a bigger factor (vs cache misses on the actual exception handler code itself, which should be reduced).
Besides, a GDT entry is 8 bytes, not 6.
-hpa
Quoted 6 lines · Ingo Molnar
.. which we were able to avoid before. A couple of segment register accesses, shifts, etc to calculate the vector - each of which can be quite costly (especially the segment register access - this is a relatively rare instruction pattern).
I'm not unconvicable, but we need to be conservative here: could you try to measure the full before/after cost of IRQ entry, to the cycle level? I'm curious what the performance impact is.
Also, this makes life probably a bit harder for Xen, which assumes that the GDT of the guest OS is small-ish. (Jeremy Cc:-ed)
It doesn't increase the GDT to more than one page, so there's no issue there. The only reason the GDT uses a whole page is because of Xen's requirements anyway, so if we can make good use of the rest of the entries, so much the better.
The other possible concern with Xen is whether Xen will properly load an arbitrary %cs on exception entry, or if it always loads KERNEL_CS; looks like it will load any %cs, so we should be fine there.
Overall the patch looks good. Saving a segment register should be much faster than loading it, so I don't think the %cs read on entry should cost too much, but reloading %cs with KERNEL_CS might be a bit more of a cost (or does it run the whole exception with the new %cs?).
J
[Alexander van Heukelum - Tue, Nov 04, 2008 at 01:28:39PM +0100]
| Hi all, | | An x86 processor handles an interrupt (from an external | source, software generated or due to an exception), | depending on the contents if the IDT. Normally the IDT | contains mostly interrupt gates. Linux points each | interrupt gate to a unique function. Some are specific | to some task (handling traps, IPI's, ...), the others | are stubs that push the interrupt number to the stack | and jump to 'common_interrupt'. | | This patch removes the need for the stubs. | | An interrupt gate contains a FAR pointer to the interrupt | handler, meaning that the code segment of the interrupt | handler is also reloaded. Instead of pointing each (non- | specific) interrupt gate to a unique handler, we set a | unique code segment and use a common handler. When the | handler finishes the code segment is restored to the | 'normal'/previous one. | | In order to have a unique code segment for each interrupt | vector, the GDT is extended to 512 entries (1 full page), | and the last half of the page describes identical code | segments (identical, except for the number in the cs | register), which are refered to by the 256 interrupt | gates. | | In this version, even the specialized handlers get run | with their code segment switched. This is not necessary, | but I like the fact that in a register dump one can now | see from the code segment that the code is ran due to | a (hard) interrupt. The exception I made is the int 0x80 | (syscall), which runs with the normal kernel code segment. | | | Concluding: changing interrupt handling to this way | removes quite a bit of source code. It also removes the | need for the interrupt stubs and, on i386, pointers to | them. This saves a few kilobytes of code. The page | reserved for the GDT is now fully used. The cs register | indicating directly that code is executed on behalf of | a (hardware) interrupt is a nice debugging aid. This way | of handling interrupts also leads to cleaner code: this | patch already gets rid of some 'ugly' macro magic in | entry_32.S and irqinit_64.c. | | More cleanup is certainly possible, but I have tried to | keep the changes local and small. If switching code | segments is too expensive for some paths, that can be | fixed by not doing that ;). | | I'ld welcome some numbers on a few benchmarks on real | hardware (I only tested on qemu: debian runs without | noticable differences before/after this patch). | | Greetings, | Alexander | | P.S. Just in case someone thinks this is a great idea and | testing and benchmarking goes well... |
...
Hi Alexander, great done!
not taking into account the cost of cs reading (which I don't suspect to be that expensive apart from writting, on the other hand I guess walking on GDT entries could be not that cheap especially with new segments you propose, I guess cpu internally check for segment to be the same and do not reload it again even if it's described as FAR pointer but I could be wrong so Andi CC'ed :)
A small nit in implementation:
entry_32.S:
+ push %eax
+ push %eax
+ mov %cs,%eax
+ shr $3,%eax
+ and $0xff,%eax
+ not %eax
+ mov %eax,4(%esp)
+ pop %eax
CFI_ADJUST_CFA_OFFSET missed?
- Cyrill -
Quoted 67 lines · Cyrill Gorcunov
[Alexander van Heukelum - Tue, Nov 04, 2008 at 01:28:39PM +0100]
| Hi all, | | An x86 processor handles an interrupt (from an external | source, software generated or due to an exception), | depending on the contents if the IDT. Normally the IDT | contains mostly interrupt gates. Linux points each | interrupt gate to a unique function. Some are specific | to some task (handling traps, IPI's, ...), the others | are stubs that push the interrupt number to the stack | and jump to 'common_interrupt'. | | This patch removes the need for the stubs. | | An interrupt gate contains a FAR pointer to the interrupt | handler, meaning that the code segment of the interrupt | handler is also reloaded. Instead of pointing each (non- | specific) interrupt gate to a unique handler, we set a | unique code segment and use a common handler. When the | handler finishes the code segment is restored to the | 'normal'/previous one. | | In order to have a unique code segment for each interrupt | vector, the GDT is extended to 512 entries (1 full page), | and the last half of the page describes identical code | segments (identical, except for the number in the cs | register), which are refered to by the 256 interrupt | gates. | | In this version, even the specialized handlers get run | with their code segment switched. This is not necessary, | but I like the fact that in a register dump one can now | see from the code segment that the code is ran due to | a (hard) interrupt. The exception I made is the int 0x80 | (syscall), which runs with the normal kernel code segment. | | | Concluding: changing interrupt handling to this way | removes quite a bit of source code. It also removes the | need for the interrupt stubs and, on i386, pointers to | them. This saves a few kilobytes of code. The page | reserved for the GDT is now fully used. The cs register | indicating directly that code is executed on behalf of | a (hardware) interrupt is a nice debugging aid. This way | of handling interrupts also leads to cleaner code: this | patch already gets rid of some 'ugly' macro magic in | entry_32.S and irqinit_64.c. | | More cleanup is certainly possible, but I have tried to | keep the changes local and small. If switching code | segments is too expensive for some paths, that can be | fixed by not doing that ;). | | I'ld welcome some numbers on a few benchmarks on real | hardware (I only tested on qemu: debian runs without | noticable differences before/after this patch). | | Greetings, | Alexander | | P.S. Just in case someone thinks this is a great idea and | testing and benchmarking goes well... |...
Hi Alexander, great done!
Quoted 7 lines
not taking into account the cost of cs reading (which I don't suspect to be that expensive apart from writting, on the other hand I guess walking on GDT entries could be not that cheap especially with new segments you propose, I guess cpu internally check for segment to be the same and do not reload it again even if it's described as FAR pointer but I could be wrong so Andi CC'ed :)
Thanks! And indeed Andi might know more about this.
I wonder how the time needed for reading the GDT segments balances against the time needed due to the extra redirection due to running the stubs. I'ld be interested if the difference can be measured with the current implementation. (I really need to highjack a machine to do some measurements; I hoped someone would do it before I got to it ;) )
Even if some CPU's have some internal optimization for the case where the gate segment is the same as the current one, I wonder if it is really important... Interrupts that occur while the processor is running userspace already cause changing segments. They are more likely to be in cache, maybe.
Greetings,
Alexander
Quoted 12 lines
A small nit in implementation:
entry_32.S:arch/x86/kernel/entry_32.S +8
-0+ push %eax + push %eax + mov %cs,%eax + shr $3,%eax + and $0xff,%eax + not %eax + mov %eax,4(%esp) + pop %eax
Quoted 1 line
CFI_ADJUST_CFA_OFFSETmissed?
Sure, I did just enough to make it work for me ;).
Quoted 1 line
- Cyrill -
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - IMAP accessible web-mail
Quoted 7 lines · Alexander van Heukelum
I wonder how the time needed for reading the GDT segments balances against the time needed due to the extra redirection due to running the stubs. I'ld be interested if the difference can be measured with the current implementation. (I really need to highjack a machine to do some measurements; I hoped someone would do it before I got to it ;) )
Quoted 5 lines
Even if some CPU's have some internal optimization for the case where the gate segment is the same as the current one, I wonder if it is really important... Interrupts that occur while the processor is running userspace already cause changing segments. They are more likely to be in cache, maybe.
there are three main factors:
- Same-value segment loads are optimized on most modern CPUs and can give a few cycles (2-3) advantage. That might or might not apply to the microcode that does IRQ entry processing. (A cache miss will increase the cost much more but that is true in general as well)
- A second effect is that the changed data structure layout: a more compressed GDT entry (6 bytes) against a more spread out (~7 bytes, not aligned) interrupt trampoline. Note that the first one is data cache the second one is instruction cache - the two have different sizes, different implementations and different hit/miss pressures. Generally the instruction-cache is the more precious resource and we optimize for that first, for data cache second.
- A third effect is branch prediction: currently we are fanning out all the vectors into ~240 branches just to recover a single constant in essence. That is quite wasteful of instruction cache resources, because from the logic side it's a data constant, not a control flow difference. (we demultiplex that number into an interrupt handler later on, but the CPU has no knowledge of that relationship)
... all in one, the situation is complex enough on the CPU architecture side for it to really necessiate a measurement in practice, and that's why i have asked you to do them: the numbers need to go hand in hand with the patch submission.
My estimation is that if we do it right, your approach will behave better on modern CPUs (which is what matters most for such things), especially on real workloads where there's a considerable instruction-cache pressure. But it should be measured in any case.
Ingo
Quoted 44 lines · Ingo Molnar
Quoted 7 lines · Alexander van Heukelum
I wonder how the time needed for reading the GDT segments balances against the time needed due to the extra redirection due to running the stubs. I'ld be interested if the difference can be measured with the current implementation. (I really need to highjack a machine to do some measurements; I hoped someone would do it before I got to it ;) )
Quoted 5 lines
Even if some CPU's have some internal optimization for the case where the gate segment is the same as the current one, I wonder if it is really important... Interrupts that occur while the processor is running userspace already cause changing segments. They are more likely to be in cache, maybe.
there are three main factors:
- Same-value segment loads are optimized on most modern CPUs and can give a few cycles (2-3) advantage. That might or might not apply to the microcode that does IRQ entry processing. (A cache miss will increase the cost much more but that is true in general as well)
- A second effect is that the changed data structure layout: a more compressed GDT entry (6 bytes) against a more spread out (~7 bytes, not aligned) interrupt trampoline. Note that the first one is data cache the second one is instruction cache - the two have different sizes, different implementations and different hit/miss pressures. Generally the instruction-cache is the more precious resource and we optimize for that first, for data cache second.
- A third effect is branch prediction: currently we are fanning out all the vectors into ~240 branches just to recover a single constant in essence. That is quite wasteful of instruction cache resources, because from the logic side it's a data constant, not a control flow difference. (we demultiplex that number into an interrupt handler later on, but the CPU has no knowledge of that relationship)
... all in one, the situation is complex enough on the CPU architecture side for it to really necessiate a measurement in practice, and that's why i have asked you to do them: the numbers need to go hand in hand with the patch submission.
Quoted 4 lines
My estimation is that if we do it right, your approach will behave better on modern CPUs (which is what matters most for such things), especially on real workloads where there's a considerable instruction-cache pressure. But it should be measured in any case.
Fully agreed. I will do some measurements in the near future, maybe next week. At least noone came up with an absolutely blocking problem with this approach ;).
Greetings,
Alexander
Quoted 1 line
Ingo
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - IMAP accessible web-mail
Quoted 8 lines · Alexander van Heukelum
Quoted 4 lines
My estimation is that if we do it right, your approach will behave better on modern CPUs (which is what matters most for such things), especially on real workloads where there's a considerable instruction-cache pressure. But it should be measured in any case.
Fully agreed. I will do some measurements in the near future, maybe next week. At least noone came up with an absolutely blocking problem with this approach ;).
how about "it does not build with lguest enabled" as a blocking problem? ;-)
arch/x86/lguest/built-in.o: In function `lguest_init_IRQ':
boot.c:(.init.text+0x33f): undefined reference to `interrupt'
config attached.
Ingo
#
# Automatically generated make config: don't edit # Linux kernel version: 2.6.28-rc3
# Tue Nov 4 17:45:25 2008
#
# CONFIG_64BIT is not setCONFIG_X86_32=y
# CONFIG_X86_64 is not setCONFIG_X86=y CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" CONFIG_GENERIC_TIME=yCONFIG_GENERIC_CMOS_UPDATE=y CONFIG_CLOCKSOURCE_WATCHDOG=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y CONFIG_FAST_CMPXCHG_LOCAL=yCONFIG_MMU=yCONFIG_ZONE_DMA=yCONFIG_GENERIC_ISA_DMA=yCONFIG_GENERIC_IOMAP=yCONFIG_GENERIC_BUG=yCONFIG_GENERIC_HWEIGHT=yCONFIG_GENERIC_GPIO=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y
# CONFIG_GENERIC_TIME_VSYSCALL is not set CONFIG_ARCH_HAS_CPU_RELAX=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y
# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_SUSPEND_POSSIBLE=y
# CONFIG_ZONE_DMA32 is not set CONFIG_ARCH_POPULATES_NODE_MAP=y
# CONFIG_AUDIT_ARCH is not set CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=yCONFIG_X86_SMP=yCONFIG_X86_32_SMP=yCONFIG_X86_HT=yCONFIG_X86_BIOS_REBOOT=yCONFIG_X86_TRAMPOLINE=yCONFIG_KTIME_SCALAR=y CONFIG_BOOTPARAM_SUPPORT_NOT_WANTED=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
#
# General setup
#CONFIG_EXPERIMENTAL=yCONFIG_BROKEN_BOOT_ALLOWED4=yCONFIG_BROKEN_BOOT_ALLOWED3=y
# CONFIG_BROKEN_BOOT_ALLOWED2 is not set
# CONFIG_BROKEN_BOOT_EUROPE is not set
# CONFIG_BROKEN_BOOT_TITAN is not setCONFIG_LOCK_KERNEL=yCONFIG_INIT_ENV_ARG_LIMIT=32CONFIG_LOCALVERSION=""CONFIG_LOCALVERSION_AUTO=yCONFIG_SWAP=yCONFIG_SYSVIPC=yCONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
# CONFIG_BSD_PROCESS_ACCT is not setCONFIG_TASKSTATS=y
# CONFIG_TASK_DELAY_ACCT is not set
# CONFIG_TASK_XACCT is not setCONFIG_AUDIT=yCONFIG_AUDITSYSCALL=yCONFIG_AUDIT_TREE=y
# CONFIG_IKCONFIG is not setCONFIG_LOG_BUF_SHIFT=21CONFIG_CGROUPS=yCONFIG_CGROUP_DEBUG=y
# CONFIG_CGROUP_NS is not setCONFIG_CGROUP_FREEZER=y
# CONFIG_CGROUP_DEVICE is not setCONFIG_CPUSETS=yCONFIG_HAVE_UNSTABLE_SCHED_CLOCK=yCONFIG_GROUP_SCHED=yCONFIG_FAIR_GROUP_SCHED=yCONFIG_RT_GROUP_SCHED=yCONFIG_USER_SCHED=y
# CONFIG_CGROUP_SCHED is not setCONFIG_CGROUP_CPUACCT=yCONFIG_RESOURCE_COUNTERS=y
# CONFIG_CGROUP_MEM_RES_CTLR is not setCONFIG_SYSFS_DEPRECATED=y
# CONFIG_SYSFS_DEPRECATED_V2 is not setCONFIG_PROC_PID_CPUSET=yCONFIG_RELAY=y
# CONFIG_NAMESPACES is not setCONFIG_BLK_DEV_INITRD=yCONFIG_INITRAMFS_SOURCE=""
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not setCONFIG_SYSCTL=yCONFIG_EMBEDDED=y
# CONFIG_UID16 is not setCONFIG_SYSCTL_SYSCALL=yCONFIG_KALLSYMS=yCONFIG_KALLSYMS_ALL=yCONFIG_KALLSYMS_EXTRA_PASS=yCONFIG_HOTPLUG=yCONFIG_PRINTK=yCONFIG_BUG=yCONFIG_ELF_CORE=yCONFIG_PCSPKR_PLATFORM=yCONFIG_COMPAT_BRK=yCONFIG_BASE_FULL=yCONFIG_FUTEX=yCONFIG_ANON_INODES=y
# CONFIG_EPOLL is not setCONFIG_SIGNALFD=yCONFIG_TIMERFD=yCONFIG_EVENTFD=yCONFIG_SHMEM=y
# CONFIG_AIO is not setCONFIG_VM_EVENT_COUNTERS=yCONFIG_PCI_QUIRKS=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_SLAB is not setCONFIG_SLUB=y
# CONFIG_SLOB is not setCONFIG_PROFILING=y
# CONFIG_MARKERS is not set
# CONFIG_OPROFILE is not setCONFIG_HAVE_OPROFILE=yCONFIG_KPROBES=yCONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=yCONFIG_KRETPROBES=yCONFIG_HAVE_IOREMAP_PROT=yCONFIG_HAVE_KPROBES=yCONFIG_HAVE_KRETPROBES=yCONFIG_HAVE_ARCH_TRACEHOOK=yCONFIG_USE_GENERIC_SMP_HELPERS=yCONFIG_HAVE_GENERIC_DMA_COHERENT=yCONFIG_RT_MUTEXES=y
# CONFIG_TINY_SHMEM is not setCONFIG_BASE_SMALL=0CONFIG_MODULES=yCONFIG_MODULE_FORCE_LOAD=y
# CONFIG_MODULE_UNLOAD is not setCONFIG_MODVERSIONS=yCONFIG_MODULE_SRCVERSION_ALL=yCONFIG_KMOD=yCONFIG_STOP_MACHINE=yCONFIG_BLOCK=yCONFIG_LBD=y
# CONFIG_BLK_DEV_IO_TRACE is not setCONFIG_LSF=yCONFIG_BLK_DEV_BSG=yCONFIG_BLK_DEV_INTEGRITY=y
#
# IO Schedulers
#CONFIG_IOSCHED_NOOP=yCONFIG_IOSCHED_AS=y
# CONFIG_IOSCHED_DEADLINE is not setCONFIG_IOSCHED_CFQ=mCONFIG_DEFAULT_AS=y
# CONFIG_DEFAULT_DEADLINE is not set
# CONFIG_DEFAULT_CFQ is not set
# CONFIG_DEFAULT_NOOP is not setCONFIG_DEFAULT_IOSCHED="anticipatory"CONFIG_PREEMPT_NOTIFIERS=yCONFIG_CLASSIC_RCU=yCONFIG_FREEZER=y
#
# Processor type and features
#CONFIG_TICK_ONESHOT=yCONFIG_NO_HZ=yCONFIG_HIGH_RES_TIMERS=yCONFIG_GENERIC_CLOCKEVENTS_BUILD=yCONFIG_SMP_SUPPORT=yCONFIG_X86_FIND_SMP_CONFIG=yCONFIG_X86_MPPARSE=y
# CONFIG_UP_WANTED_1 is not setCONFIG_SMP=yCONFIG_X86_PC=y
# CONFIG_X86_ELAN is not set
# CONFIG_X86_VOYAGER is not set
# CONFIG_X86_GENERICARCH is not set
# CONFIG_X86_VSMP is not setCONFIG_X86_RDC321X=yCONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=yCONFIG_PARAVIRT_GUEST=y
# CONFIG_VMI is not set
# CONFIG_KVM_CLOCK is not setCONFIG_KVM_GUEST=yCONFIG_LGUEST_GUEST=yCONFIG_PARAVIRT=y
# CONFIG_PARAVIRT_CLOCK is not setCONFIG_MEMTEST=y
# CONFIG_M386 is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
# CONFIG_M586TSC is not set
# CONFIG_M586MMX is not setCONFIG_M686=y
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MGEODEGX1 is not set
# CONFIG_MGEODE_LX is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MPSC is not set
# CONFIG_MCORE2 is not set
# CONFIG_GENERIC_CPU is not setCONFIG_X86_GENERIC=yCONFIG_X86_CPU=yCONFIG_X86_CMPXCHG=yCONFIG_X86_L1_CACHE_SHIFT=7CONFIG_X86_XADD=yCONFIG_X86_PPRO_FENCE=yCONFIG_X86_WP_WORKS_OK=yCONFIG_X86_INVLPG=yCONFIG_X86_BSWAP=yCONFIG_X86_POPAD_OK=yCONFIG_X86_INTEL_USERCOPY=yCONFIG_X86_USE_PPRO_CHECKSUM=yCONFIG_X86_TSC=yCONFIG_X86_CMOV=yCONFIG_X86_MINIMUM_CPU_FAMILY=4CONFIG_X86_DEBUGCTLMSR=y
# CONFIG_PROCESSOR_SELECT is not setCONFIG_CPU_SUP_INTEL=yCONFIG_CPU_SUP_CYRIX_32=yCONFIG_CPU_SUP_AMD=yCONFIG_CPU_SUP_CENTAUR_32=yCONFIG_CPU_SUP_TRANSMETA_32=yCONFIG_CPU_SUP_UMC_32=yCONFIG_X86_DS=yCONFIG_X86_PTRACE_BTS=yCONFIG_HPET_TIMER=yCONFIG_HPET_EMULATE_RTC=y
# CONFIG_DMI is not set
# CONFIG_IOMMU_HELPER is not setCONFIG_NR_CPUS=8CONFIG_SCHED_SMT=yCONFIG_SCHED_MC=yCONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not setCONFIG_CPUMASK_OFFSTACK=yCONFIG_X86_LOCAL_APIC=yCONFIG_X86_IO_APIC=yCONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=yCONFIG_X86_MCE=yCONFIG_X86_MCE_NONFATAL=yCONFIG_X86_MCE_P4THERMAL=y
# CONFIG_VM86 is not setCONFIG_TOSHIBA=y
# CONFIG_I8K is not setCONFIG_X86_REBOOTFIXUPS=yCONFIG_MICROCODE=m
# CONFIG_MICROCODE_INTEL is not setCONFIG_MICROCODE_AMD=yCONFIG_MICROCODE_OLD_INTERFACE=y
# CONFIG_X86_MSR is not set
# CONFIG_X86_CPUID is not set
# CONFIG_NOHIGHMEM is not setCONFIG_HIGHMEM4G=y
# CONFIG_HIGHMEM64G is not setCONFIG_VMSPLIT_3G=y
# CONFIG_VMSPLIT_3G_OPT is not set
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_2G_OPT is not set
# CONFIG_VMSPLIT_1G is not setCONFIG_PAGE_OFFSET=0xC0000000CONFIG_HIGHMEM=y
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not setCONFIG_ARCH_FLATMEM_ENABLE=yCONFIG_ARCH_SPARSEMEM_ENABLE=yCONFIG_ARCH_SELECT_MEMORY_MODEL=yCONFIG_ILLEGAL_POINTER_VALUE=0CONFIG_SELECT_MEMORY_MODEL=yCONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not setCONFIG_FLATMEM=yCONFIG_FLAT_NODE_MEM_MAP=yCONFIG_SPARSEMEM_STATIC=yCONFIG_PAGEFLAGS_EXTENDED=yCONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_RESOURCES_64BIT is not set
# CONFIG_PHYS_ADDR_T_64BIT is not setCONFIG_ZONE_DMA_FLAG=1CONFIG_BOUNCE=yCONFIG_VIRT_TO_BUS=yCONFIG_UNEVICTABLE_LRU=yCONFIG_MMU_NOTIFIER=yCONFIG_HIGHPTE=yCONFIG_X86_CHECK_BIOS_CORRUPTION=yCONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=yCONFIG_X86_RESERVE_LOW_64K=yCONFIG_MATH_EMULATION=yCONFIG_MTRR=yCONFIG_MTRR_SANITIZER=yCONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
# CONFIG_X86_PAT is not setCONFIG_EFI=y
# CONFIG_SECCOMP is not set
# CONFIG_HZ_100 is not setCONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not setCONFIG_HZ=250CONFIG_SCHED_HRTICK=yCONFIG_KEXEC=yCONFIG_CRASH_DUMP=yCONFIG_KEXEC_JUMP=yCONFIG_PHYSICAL_START=0x100000CONFIG_RELOCATABLE=yCONFIG_PHYSICAL_ALIGN=0x100000CONFIG_HOTPLUG_CPU=y
# CONFIG_COMPAT_VDSO is not setCONFIG_CMDLINE_BOOL=yCONFIG_CMDLINE=""CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
#
# Power management options
#CONFIG_PM=yCONFIG_PM_DEBUG=y
# CONFIG_PM_VERBOSE is not setCONFIG_CAN_PM_TRACE=yCONFIG_PM_TRACE=yCONFIG_PM_TRACE_RTC=yCONFIG_PM_SLEEP_SMP=yCONFIG_PM_SLEEP=y
# CONFIG_SUSPEND is not setCONFIG_HIBERNATION=yCONFIG_PM_STD_PARTITION=""CONFIG_ACPI=yCONFIG_ACPI_SLEEP=yCONFIG_ACPI_PROCFS=yCONFIG_ACPI_PROCFS_POWER=yCONFIG_ACPI_SYSFS_POWER=y
# CONFIG_ACPI_PROC_EVENT is not set
# CONFIG_ACPI_AC is not setCONFIG_ACPI_BATTERY=mCONFIG_ACPI_BUTTON=mCONFIG_ACPI_FAN=y
# CONFIG_ACPI_DOCK is not set
# CONFIG_ACPI_PROCESSOR is not setCONFIG_ACPI_WMI=yCONFIG_ACPI_ASUS=mCONFIG_ACPI_TOSHIBA=m
# CONFIG_ACPI_CUSTOM_DSDT is not setCONFIG_ACPI_BLACKLIST_YEAR=0CONFIG_ACPI_DEBUG=y
# CONFIG_ACPI_DEBUG_FUNC_TRACE is not setCONFIG_ACPI_EC=yCONFIG_ACPI_PCI_SLOT=mCONFIG_ACPI_POWER=yCONFIG_ACPI_SYSTEM=y
# CONFIG_X86_PM_TIMER is not set
# CONFIG_ACPI_CONTAINER is not setCONFIG_ACPI_SBS=m
# CONFIG_APM is not set
#
# CPU Frequency scaling
#CONFIG_CPU_FREQ=yCONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set CONFIG_CPU_FREQ_GOV_USERSPACE=m CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
#
# CPUFreq processor drivers
#CONFIG_X86_POWERNOW_K6=y
# CONFIG_X86_POWERNOW_K7 is not setCONFIG_X86_POWERNOW_K8=m
# CONFIG_X86_GX_SUSPMOD is not setCONFIG_X86_SPEEDSTEP_CENTRINO=mCONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=yCONFIG_X86_SPEEDSTEP_ICH=yCONFIG_X86_SPEEDSTEP_SMI=yCONFIG_X86_P4_CLOCKMOD=m
# CONFIG_X86_CPUFREQ_NFORCE2 is not set
# CONFIG_X86_LONGRUN is not setCONFIG_X86_E_POWERSAVER=m
#
# shared options # CONFIG_X86_SPEEDSTEP_LIB=y # CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPU_IDLE_GOV_MENU=y
#
# Memory power savings
#
#
# Bus options (PCI etc.)
#CONFIG_PCI=y
# CONFIG_PCI_GOBIOS is not set
# CONFIG_PCI_GOMMCONFIG is not set
# CONFIG_PCI_GODIRECT is not set
# CONFIG_PCI_GOOLPC is not setCONFIG_PCI_GOANY=yCONFIG_PCI_BIOS=yCONFIG_PCI_DIRECT=yCONFIG_PCI_MMCONFIG=yCONFIG_PCI_DOMAINS=yCONFIG_PCIEPORTBUS=yCONFIG_HOTPLUG_PCI_PCIE=mCONFIG_PCIEAER=yCONFIG_PCIEASPM=y
# CONFIG_PCIEASPM_DEBUG is not setCONFIG_ARCH_SUPPORTS_MSI=yCONFIG_PCI_MSI=yCONFIG_PCI_LEGACY=y
# CONFIG_HT_IRQ is not setCONFIG_ISA_DMA_API=y
# CONFIG_ISA is not setCONFIG_MCA=yCONFIG_MCA_LEGACY=yCONFIG_MCA_PROC_FS=y
# CONFIG_SCx200 is not set
# CONFIG_OLPC is not setCONFIG_K8_NB=yCONFIG_PCCARD=mCONFIG_PCMCIA_DEBUG=y
# CONFIG_PCMCIA is not set
# CONFIG_CARDBUS is not set
#
# PC-card bridges
#CONFIG_YENTA=m
# CONFIG_YENTA_O2 is not set
# CONFIG_YENTA_RICOH is not set
# CONFIG_YENTA_TI is not set
# CONFIG_YENTA_TOSHIBA is not setCONFIG_PCCARD_NONSTATIC=mCONFIG_HOTPLUG_PCI=mCONFIG_HOTPLUG_PCI_FAKE=mCONFIG_HOTPLUG_PCI_COMPAQ=mCONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=yCONFIG_HOTPLUG_PCI_IBM=mCONFIG_HOTPLUG_PCI_ACPI=mCONFIG_HOTPLUG_PCI_ACPI_IBM=m
# CONFIG_HOTPLUG_PCI_CPCI is not setCONFIG_HOTPLUG_PCI_SHPC=m
#
# Executable file formats / Emulations
#CONFIG_BINFMT_ELF=yCONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=yCONFIG_HAVE_AOUT=yCONFIG_BINFMT_AOUT=yCONFIG_BINFMT_MISC=yCONFIG_HAVE_ATOMIC_IOMAP=yCONFIG_NET=y
#
# Networking options
#CONFIG_PACKET=yCONFIG_PACKET_MMAP=yCONFIG_UNIX=yCONFIG_XFRM=yCONFIG_XFRM_USER=mCONFIG_XFRM_SUB_POLICY=yCONFIG_XFRM_MIGRATE=yCONFIG_XFRM_STATISTICS=yCONFIG_XFRM_IPCOMP=yCONFIG_NET_KEY=yCONFIG_NET_KEY_MIGRATE=yCONFIG_INET=yCONFIG_IP_MULTICAST=yCONFIG_IP_ADVANCED_ROUTER=yCONFIG_ASK_IP_FIB_HASH=y
# CONFIG_IP_FIB_TRIE is not setCONFIG_IP_FIB_HASH=yCONFIG_IP_MULTIPLE_TABLES=yCONFIG_IP_ROUTE_MULTIPATH=y
# CONFIG_IP_ROUTE_VERBOSE is not set
# CONFIG_IP_PNP is not setCONFIG_NET_IPIP=mCONFIG_NET_IPGRE=yCONFIG_NET_IPGRE_BROADCAST=y
# CONFIG_IP_MROUTE is not set
# CONFIG_ARPD is not setCONFIG_SYN_COOKIES=yCONFIG_INET_AH=mCONFIG_INET_ESP=mCONFIG_INET_IPCOMP=yCONFIG_INET_XFRM_TUNNEL=yCONFIG_INET_TUNNEL=yCONFIG_INET_XFRM_MODE_TRANSPORT=yCONFIG_INET_XFRM_MODE_TUNNEL=y
# CONFIG_INET_XFRM_MODE_BEET is not setCONFIG_INET_LRO=mCONFIG_INET_DIAG=mCONFIG_INET_TCP_DIAG=mCONFIG_TCP_CONG_ADVANCED=yCONFIG_TCP_CONG_BIC=m
# CONFIG_TCP_CONG_CUBIC is not setCONFIG_TCP_CONG_WESTWOOD=y
# CONFIG_TCP_CONG_HTCP is not setCONFIG_TCP_CONG_HSTCP=y
# CONFIG_TCP_CONG_HYBLA is not setCONFIG_TCP_CONG_VEGAS=y
# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_TCP_CONG_LP is not setCONFIG_TCP_CONG_VENO=mCONFIG_TCP_CONG_YEAH=yCONFIG_TCP_CONG_ILLINOIS=y
# CONFIG_DEFAULT_BIC is not set
# CONFIG_DEFAULT_CUBIC is not set
# CONFIG_DEFAULT_HTCP is not setCONFIG_DEFAULT_VEGAS=y
# CONFIG_DEFAULT_WESTWOOD is not set
# CONFIG_DEFAULT_RENO is not setCONFIG_DEFAULT_TCP_CONG="vegas"CONFIG_TCP_MD5SIG=yCONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not setCONFIG_IPV6_ROUTER_PREF=y
# CONFIG_IPV6_ROUTE_INFO is not set
# CONFIG_IPV6_OPTIMISTIC_DAD is not setCONFIG_INET6_AH=mCONFIG_INET6_ESP=yCONFIG_INET6_IPCOMP=m
# CONFIG_IPV6_MIP6 is not setCONFIG_INET6_XFRM_TUNNEL=mCONFIG_INET6_TUNNEL=mCONFIG_INET6_XFRM_MODE_TRANSPORT=yCONFIG_INET6_XFRM_MODE_TUNNEL=mCONFIG_INET6_XFRM_MODE_BEET=mCONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=mCONFIG_IPV6_SIT=yCONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_TUNNEL is not setCONFIG_IPV6_MULTIPLE_TABLES=yCONFIG_IPV6_SUBTREES=y
# CONFIG_IPV6_MROUTE is not setCONFIG_NETLABEL=yCONFIG_NETWORK_SECMARK=yCONFIG_NETFILTER=yCONFIG_NETFILTER_DEBUG=y
# CONFIG_NETFILTER_ADVANCED is not set
#
# Core Netfilter Configuration
#CONFIG_NETFILTER_NETLINK=y
# CONFIG_NETFILTER_NETLINK_LOG is not setCONFIG_NF_CONNTRACK=y
# CONFIG_NF_CONNTRACK_SECMARK is not set
# CONFIG_NF_CONNTRACK_FTP is not set
# CONFIG_NF_CONNTRACK_IRC is not set
# CONFIG_NF_CONNTRACK_SIP is not setCONFIG_NF_CT_NETLINK=yCONFIG_NETFILTER_XTABLES=yCONFIG_NETFILTER_XT_TARGET_MARK=yCONFIG_NETFILTER_XT_TARGET_NFLOG=mCONFIG_NETFILTER_XT_TARGET_SECMARK=yCONFIG_NETFILTER_XT_TARGET_TCPMSS=mCONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
# CONFIG_NETFILTER_XT_MATCH_MARK is not setCONFIG_NETFILTER_XT_MATCH_POLICY=mCONFIG_NETFILTER_XT_MATCH_STATE=yCONFIG_IP_VS=yCONFIG_IP_VS_IPV6=y
# CONFIG_IP_VS_DEBUG is not setCONFIG_IP_VS_TAB_BITS=12
#
# IPVS transport protocol load balancing support
#CONFIG_IP_VS_PROTO_TCP=y
# CONFIG_IP_VS_PROTO_UDP is not setCONFIG_IP_VS_PROTO_AH_ESP=yCONFIG_IP_VS_PROTO_ESP=yCONFIG_IP_VS_PROTO_AH=y
#
# IPVS scheduler
#CONFIG_IP_VS_RR=m
# CONFIG_IP_VS_WRR is not set
# CONFIG_IP_VS_LC is not setCONFIG_IP_VS_WLC=mCONFIG_IP_VS_LBLC=mCONFIG_IP_VS_LBLCR=yCONFIG_IP_VS_DH=mCONFIG_IP_VS_SH=m
# CONFIG_IP_VS_SED is not setCONFIG_IP_VS_NQ=y
#
# IPVS application helper
#
# CONFIG_IP_VS_FTP is not set
#
# IP: Netfilter Configuration
#CONFIG_NF_DEFRAG_IPV4=mCONFIG_NF_CONNTRACK_IPV4=mCONFIG_NF_CONNTRACK_PROC_COMPAT=yCONFIG_IP_NF_IPTABLES=mCONFIG_IP_NF_FILTER=m
# CONFIG_IP_NF_TARGET_REJECT is not setCONFIG_IP_NF_TARGET_LOG=mCONFIG_IP_NF_TARGET_ULOG=mCONFIG_NF_NAT=mCONFIG_NF_NAT_NEEDED=yCONFIG_IP_NF_TARGET_MASQUERADE=m
# CONFIG_NF_NAT_FTP is not set
# CONFIG_NF_NAT_IRC is not set
# CONFIG_NF_NAT_TFTP is not set
# CONFIG_NF_NAT_AMANDA is not set
# CONFIG_NF_NAT_PPTP is not set
# CONFIG_NF_NAT_H323 is not set
# CONFIG_NF_NAT_SIP is not setCONFIG_IP_NF_MANGLE=m
#
# IPv6: Netfilter Configuration
#CONFIG_NF_CONNTRACK_IPV6=yCONFIG_IP6_NF_IPTABLES=y
# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
# CONFIG_IP6_NF_TARGET_LOG is not set
# CONFIG_IP6_NF_FILTER is not set
# CONFIG_IP6_NF_MANGLE is not set
# CONFIG_IP_DCCP is not setCONFIG_IP_SCTP=y
# CONFIG_SCTP_DBG_MSG is not setCONFIG_SCTP_DBG_OBJCNT=y
# CONFIG_SCTP_HMAC_NONE is not set
# CONFIG_SCTP_HMAC_SHA1 is not setCONFIG_SCTP_HMAC_MD5=yCONFIG_TIPC=m
# CONFIG_TIPC_ADVANCED is not setCONFIG_TIPC_DEBUG=y
# CONFIG_ATM is not setCONFIG_STP=yCONFIG_GARP=yCONFIG_BRIDGE=mCONFIG_NET_DSA=yCONFIG_NET_DSA_TAG_DSA=yCONFIG_NET_DSA_TAG_EDSA=y
# CONFIG_NET_DSA_TAG_TRAILER is not setCONFIG_NET_DSA_MV88E6XXX=y
# CONFIG_NET_DSA_MV88E6060 is not setCONFIG_NET_DSA_MV88E6XXX_NEED_PPU=yCONFIG_NET_DSA_MV88E6131=yCONFIG_NET_DSA_MV88E6123_61_65=yCONFIG_VLAN_8021Q=yCONFIG_VLAN_8021Q_GVRP=y
# CONFIG_DECNET is not setCONFIG_LLC=yCONFIG_LLC2=m
# CONFIG_IPX is not setCONFIG_ATALK=mCONFIG_DEV_APPLETALK=mCONFIG_IPDDP=mCONFIG_IPDDP_ENCAP=yCONFIG_IPDDP_DECAP=y
# CONFIG_X25 is not setCONFIG_LAPB=yCONFIG_ECONET=mCONFIG_ECONET_AUNUDP=y
# CONFIG_ECONET_NATIVE is not setCONFIG_WAN_ROUTER=yCONFIG_NET_SCHED=y
#
# Queueing/Scheduling
#CONFIG_NET_SCH_CBQ=y
# CONFIG_NET_SCH_HTB is not set
# CONFIG_NET_SCH_HFSC is not setCONFIG_NET_SCH_PRIO=yCONFIG_NET_SCH_MULTIQ=m
# CONFIG_NET_SCH_RED is not set
# CONFIG_NET_SCH_SFQ is not setCONFIG_NET_SCH_TEQL=y
# CONFIG_NET_SCH_TBF is not setCONFIG_NET_SCH_GRED=y
# CONFIG_NET_SCH_DSMARK is not set
# CONFIG_NET_SCH_NETEM is not setCONFIG_NET_SCH_INGRESS=y
#
# Classification
#CONFIG_NET_CLS=yCONFIG_NET_CLS_BASIC=yCONFIG_NET_CLS_TCINDEX=mCONFIG_NET_CLS_ROUTE4=yCONFIG_NET_CLS_ROUTE=yCONFIG_NET_CLS_FW=mCONFIG_NET_CLS_U32=mCONFIG_CLS_U32_PERF=y
# CONFIG_CLS_U32_MARK is not set
# CONFIG_NET_CLS_RSVP is not setCONFIG_NET_CLS_RSVP6=yCONFIG_NET_CLS_FLOW=mCONFIG_NET_EMATCH=yCONFIG_NET_EMATCH_STACK=32CONFIG_NET_EMATCH_CMP=y
# CONFIG_NET_EMATCH_NBYTE is not set
# CONFIG_NET_EMATCH_U32 is not setCONFIG_NET_EMATCH_META=mCONFIG_NET_EMATCH_TEXT=yCONFIG_NET_CLS_ACT=y
# CONFIG_NET_ACT_POLICE is not setCONFIG_NET_ACT_GACT=yCONFIG_GACT_PROB=yCONFIG_NET_ACT_MIRRED=yCONFIG_NET_ACT_IPT=m
# CONFIG_NET_ACT_NAT is not set
# CONFIG_NET_ACT_PEDIT is not set
# CONFIG_NET_ACT_SIMP is not setCONFIG_NET_ACT_SKBEDIT=y
# CONFIG_NET_CLS_IND is not setCONFIG_NET_SCH_FIFO=y
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_TCPPROBE is not setCONFIG_HAMRADIO=y
#
# Packet Radio protocols
#
# CONFIG_AX25 is not set
# CONFIG_CAN is not setCONFIG_IRDA=y
#
# IrDA protocols
#CONFIG_IRLAN=yCONFIG_IRCOMM=mCONFIG_IRDA_ULTRA=y
#
# IrDA options
#
# CONFIG_IRDA_CACHE_LAST_LSAP is not setCONFIG_IRDA_FAST_RR=yCONFIG_IRDA_DEBUG=y
#
# Infrared-port device drivers
#
#
# SIR device drivers
#CONFIG_IRTTY_SIR=m
#
# Dongle support
#CONFIG_DONGLE=yCONFIG_ESI_DONGLE=mCONFIG_ACTISYS_DONGLE=mCONFIG_TEKRAM_DONGLE=mCONFIG_TOIM3232_DONGLE=mCONFIG_LITELINK_DONGLE=m
# CONFIG_MA600_DONGLE is not setCONFIG_GIRBIL_DONGLE=m
# CONFIG_MCP2120_DONGLE is not setCONFIG_OLD_BELKIN_DONGLE=mCONFIG_ACT200L_DONGLE=mCONFIG_KINGSUN_DONGLE=yCONFIG_KSDAZZLE_DONGLE=y
# CONFIG_KS959_DONGLE is not set
#
# FIR device drivers
#
# CONFIG_USB_IRDA is not setCONFIG_SIGMATEL_FIR=mCONFIG_NSC_FIR=mCONFIG_WINBOND_FIR=mCONFIG_TOSHIBA_FIR=yCONFIG_SMC_IRCC_FIR=m
# CONFIG_ALI_FIR is not set
# CONFIG_VLSI_FIR is not set
# CONFIG_VIA_FIR is not set
# CONFIG_MCS_FIR is not setCONFIG_BT=mCONFIG_BT_L2CAP=mCONFIG_BT_SCO=mCONFIG_BT_RFCOMM=mCONFIG_BT_RFCOMM_TTY=y
# CONFIG_BT_BNEP is not setCONFIG_BT_HIDP=m
#
# Bluetooth device drivers
#CONFIG_BT_HCIBTUSB=mCONFIG_BT_HCIBTSDIO=mCONFIG_BT_HCIUART=mCONFIG_BT_HCIUART_H4=yCONFIG_BT_HCIUART_BCSP=y
# CONFIG_BT_HCIUART_LL is not setCONFIG_BT_HCIBCM203X=mCONFIG_BT_HCIBPA10X=mCONFIG_BT_HCIBFUSB=mCONFIG_BT_HCIVHCI=m
# CONFIG_AF_RXRPC is not set
# CONFIG_PHONET is not setCONFIG_FIB_RULES=yCONFIG_WIRELESS=yCONFIG_CFG80211=m
# CONFIG_NL80211 is not setCONFIG_WIRELESS_OLD_REGULATORY=yCONFIG_WIRELESS_EXT=yCONFIG_WIRELESS_EXT_SYSFS=y
# CONFIG_MAC80211 is not set
# CONFIG_IEEE80211 is not setCONFIG_RFKILL=y
# CONFIG_RFKILL_INPUT is not setCONFIG_RFKILL_LEDS=y
#
# Device Drivers
#
#
# Generic Driver Options
#CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"CONFIG_STANDALONE=yCONFIG_PREVENT_FIRMWARE_BUILD=yCONFIG_FW_LOADER=y
# CONFIG_FIRMWARE_IN_KERNEL is not setCONFIG_EXTRA_FIRMWARE=""
# CONFIG_SYS_HYPERVISOR is not setCONFIG_CONNECTOR=yCONFIG_PROC_EVENTS=y
# CONFIG_PARPORT is not setCONFIG_PNP=y
# CONFIG_PNP_DEBUG_MESSAGES is not set
#
# Protocols
#CONFIG_PNPACPI=yCONFIG_BLK_DEV=yCONFIG_BLK_DEV_FD=yCONFIG_BLK_CPQ_DA=y
# CONFIG_BLK_CPQ_CISS_DA is not setCONFIG_BLK_DEV_DAC960=m
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_COW_COMMON is not setCONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not setCONFIG_BLK_DEV_NBD=yCONFIG_BLK_DEV_SX8=mCONFIG_BLK_DEV_UB=mCONFIG_BLK_DEV_RAM=mCONFIG_BLK_DEV_RAM_COUNT=16CONFIG_BLK_DEV_RAM_SIZE=4096CONFIG_BLK_DEV_XIP=yCONFIG_CDROM_PKTCDVD=mCONFIG_CDROM_PKTCDVD_BUFFERS=8CONFIG_CDROM_PKTCDVD_WCACHE=y
# CONFIG_ATA_OVER_ETH is not set
# CONFIG_VIRTIO_BLK is not setCONFIG_BLK_DEV_HD=y
# CONFIG_MISC_DEVICES is not setCONFIG_TIFM_CORE=mCONFIG_HAVE_IDE=y
#
# SCSI device support
#CONFIG_RAID_ATTRS=yCONFIG_SCSI=yCONFIG_SCSI_DMA=yCONFIG_SCSI_TGT=mCONFIG_SCSI_NETLINK=y
# CONFIG_SCSI_PROC_FS is not set
#
# SCSI support type (disk, tape, CD-ROM)
#CONFIG_BLK_DEV_SD=yCONFIG_CHR_DEV_ST=mCONFIG_CHR_DEV_OSST=yCONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not setCONFIG_CHR_DEV_SG=mCONFIG_CHR_DEV_SCH=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs #CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set CONFIG_SCSI_LOGGING=yCONFIG_SCSI_SCAN_ASYNC=yCONFIG_SCSI_WAIT_SCAN=m
#
# SCSI Transports
#CONFIG_SCSI_SPI_ATTRS=yCONFIG_SCSI_FC_ATTRS=yCONFIG_SCSI_ISCSI_ATTRS=yCONFIG_SCSI_SAS_ATTRS=yCONFIG_SCSI_SRP_ATTRS=yCONFIG_SCSI_LOWLEVEL=y
# CONFIG_ISCSI_TCP is not setCONFIG_BLK_DEV_3W_XXXX_RAID=mCONFIG_SCSI_3W_9XXX=yCONFIG_SCSI_ACARD=yCONFIG_SCSI_AACRAID=mCONFIG_SCSI_AIC7XXX=yCONFIG_AIC7XXX_CMDS_PER_DEVICE=32CONFIG_AIC7XXX_RESET_DELAY_MS=5000CONFIG_AIC7XXX_DEBUG_ENABLE=yCONFIG_AIC7XXX_DEBUG_MASK=0
# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not setCONFIG_SCSI_AIC7XXX_OLD=mCONFIG_SCSI_AIC79XX=yCONFIG_AIC79XX_CMDS_PER_DEVICE=32CONFIG_AIC79XX_RESET_DELAY_MS=5000CONFIG_AIC79XX_DEBUG_ENABLE=yCONFIG_AIC79XX_DEBUG_MASK=0CONFIG_AIC79XX_REG_PRETTY_PRINT=y
# CONFIG_SCSI_DPT_I2O is not setCONFIG_SCSI_ADVANSYS=mCONFIG_SCSI_ARCMSR=y
# CONFIG_SCSI_ARCMSR_AER is not setCONFIG_MEGARAID_NEWGEN=y
# CONFIG_MEGARAID_MM is not setCONFIG_MEGARAID_LEGACY=m
# CONFIG_MEGARAID_SAS is not setCONFIG_SCSI_HPTIOP=mCONFIG_SCSI_BUSLOGIC=yCONFIG_SCSI_FLASHPOINT=yCONFIG_SCSI_DMX3191D=y
# CONFIG_SCSI_EATA is not setCONFIG_SCSI_FUTURE_DOMAIN=m
# CONFIG_SCSI_FD_MCS is not setCONFIG_SCSI_GDTH=mCONFIG_SCSI_IBMMCA=mCONFIG_IBMMCA_SCSI_ORDER_STANDARD=yCONFIG_IBMMCA_SCSI_DEV_RESET=yCONFIG_SCSI_IPS=mCONFIG_SCSI_INITIO=mCONFIG_SCSI_INIA100=y
# CONFIG_SCSI_NCR_D700 is not set
# CONFIG_SCSI_STEX is not set
# CONFIG_SCSI_SYM53C8XX_2 is not setCONFIG_SCSI_IPR=mCONFIG_SCSI_IPR_TRACE=yCONFIG_SCSI_IPR_DUMP=y
# CONFIG_SCSI_NCR_Q720 is not setCONFIG_SCSI_QLOGIC_1280=mCONFIG_SCSI_QLA_FC=y
# CONFIG_SCSI_QLA_ISCSI is not setCONFIG_SCSI_LPFC=yCONFIG_SCSI_SIM710=y
CONFIG_SCSI_DC395x=mCONFIG_SCSI_DC390T=y
# CONFIG_SCSI_NSP32 is not setCONFIG_SCSI_SRP=mCONFIG_SCSI_DH=m
# CONFIG_SCSI_DH_RDAC is not setCONFIG_SCSI_DH_HP_SW=mCONFIG_SCSI_DH_EMC=mCONFIG_SCSI_DH_ALUA=mCONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_ATA_ACPI is not set
# CONFIG_SATA_PMP is not setCONFIG_SATA_AHCI=y
# CONFIG_SATA_SIL24 is not setCONFIG_ATA_SFF=yCONFIG_SATA_SVW=yCONFIG_ATA_PIIX=y
# CONFIG_SATA_MV is not setCONFIG_SATA_NV=y
# CONFIG_PDC_ADMA is not setCONFIG_SATA_QSTOR=mCONFIG_SATA_PROMISE=mCONFIG_SATA_SX4=yCONFIG_SATA_SIL=m
# CONFIG_SATA_SIS is not setCONFIG_SATA_ULI=mCONFIG_SATA_VIA=m
# CONFIG_SATA_VITESSE is not setCONFIG_SATA_INIC162X=m
# CONFIG_PATA_ALI is not setCONFIG_PATA_AMD=yCONFIG_PATA_ARTOP=mCONFIG_PATA_ATIIXP=mCONFIG_PATA_CMD640_PCI=yCONFIG_PATA_CMD64X=y
# CONFIG_PATA_CS5520 is not setCONFIG_PATA_CS5530=mCONFIG_PATA_CS5535=mCONFIG_PATA_CS5536=y
# CONFIG_PATA_CYPRESS is not set
# CONFIG_PATA_EFAR is not set
# CONFIG_ATA_GENERIC is not setCONFIG_PATA_HPT366=mCONFIG_PATA_HPT37X=mCONFIG_PATA_HPT3X2N=yCONFIG_PATA_HPT3X3=yCONFIG_PATA_HPT3X3_DMA=y
# CONFIG_PATA_IT821X is not setCONFIG_PATA_IT8213=yCONFIG_PATA_JMICRON=m
# CONFIG_PATA_TRIFLEX is not setCONFIG_PATA_MARVELL=mCONFIG_PATA_MPIIX=mCONFIG_PATA_OLDPIIX=y
# CONFIG_PATA_NETCELL is not setCONFIG_PATA_NINJA32=y
# CONFIG_PATA_NS87410 is not setCONFIG_PATA_NS87415=m
# CONFIG_PATA_OPTI is not setCONFIG_PATA_OPTIDMA=yCONFIG_PATA_PDC_OLD=y
# CONFIG_PATA_RADISYS is not setCONFIG_PATA_RZ1000=yCONFIG_PATA_SC1200=yCONFIG_PATA_SERVERWORKS=m
# CONFIG_PATA_PDC2027X is not setCONFIG_PATA_SIL680=yCONFIG_PATA_SIS=yCONFIG_PATA_VIA=yCONFIG_PATA_WINBOND=m
# CONFIG_PATA_PLATFORM is not setCONFIG_PATA_SCH=m
# CONFIG_MD is not set
# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
#
#
# Enable only one of the two stacks, unless you know what you are doing #CONFIG_FIREWIRE=mCONFIG_FIREWIRE_OHCI=mCONFIG_FIREWIRE_OHCI_DEBUG=yCONFIG_FIREWIRE_SBP2=mCONFIG_IEEE1394=y
# CONFIG_IEEE1394_OHCI1394 is not set
# CONFIG_IEEE1394_PCILYNX is not set
# CONFIG_IEEE1394_SBP2 is not set CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y CONFIG_IEEE1394_ETH1394=yCONFIG_IEEE1394_RAWIO=mCONFIG_IEEE1394_VERBOSEDEBUG=yCONFIG_I2O=mCONFIG_I2O_LCT_NOTIFY_ON_CHANGES=yCONFIG_I2O_EXT_ADAPTEC=yCONFIG_I2O_CONFIG=mCONFIG_I2O_CONFIG_OLD_IOCTL=y
# CONFIG_I2O_BUS is not set
# CONFIG_I2O_BLOCK is not setCONFIG_I2O_SCSI=m
# CONFIG_I2O_PROC is not set
# CONFIG_MACINTOSH_DRIVERS is not setCONFIG_NETDEVICES=yCONFIG_IFB=yCONFIG_DUMMY=yCONFIG_BONDING=mCONFIG_MACVLAN=yCONFIG_EQUALIZER=y
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_NET_SB1000 is not set
# CONFIG_ARCNET is not setCONFIG_PHYLIB=y
#
# MII PHY device drivers
#
# CONFIG_MARVELL_PHY is not set CONFIG_DAVICOM_PHY=m
# CONFIG_QSEMI_PHY is not set CONFIG_LXT_PHY=y
# CONFIG_CICADA_PHY is not set CONFIG_VITESSE_PHY=mCONFIG_SMSC_PHY=mCONFIG_BROADCOM_PHY=yCONFIG_ICPLUS_PHY=m
# CONFIG_REALTEK_PHY is not set CONFIG_FIXED_PHY=y
# CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=yCONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set CONFIG_NET_VENDOR_3COM=y
# CONFIG_EL3 is not set
# CONFIG_ELMC is not set
# CONFIG_ELMC_II is not set CONFIG_VORTEX=yCONFIG_TYPHOON=m
# CONFIG_NET_VENDOR_SMC is not set CONFIG_ENC28J60=m CONFIG_ENC28J60_WRITEVERIFY=y
# CONFIG_NET_TULIP is not set CONFIG_AT1700=mCONFIG_DEPCA=mCONFIG_HP100=m
# CONFIG_NE2_MCA is not set
# CONFIG_IBMLANA is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set CONFIG_ADAPTEC_STARFIRE=mCONFIG_B44=mCONFIG_B44_PCI_AUTOSELECT=y CONFIG_B44_PCICORE_AUTOSELECT=y CONFIG_B44_PCI=yCONFIG_FORCEDETH=y
# CONFIG_FORCEDETH_NAPI is not set CONFIG_EEPRO100=yCONFIG_E100=yCONFIG_FEALNX=yCONFIG_NATSEMI=yCONFIG_NE2K_PCI=mCONFIG_8139CP=mCONFIG_8139TOO=y
# CONFIG_8139TOO_PIO is not set
# CONFIG_8139TOO_TUNE_TWISTER is not set CONFIG_8139TOO_8129=y CONFIG_8139_OLD_RX_RESET=y
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set CONFIG_EPIC100=m
# CONFIG_SUNDANCE is not setCONFIG_TLAN=y
# CONFIG_VIA_RHINE is not set CONFIG_SC92031=yCONFIG_ATL2=mCONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not setCONFIG_DL2K=y
# CONFIG_E1000 is not setCONFIG_E1000E=yCONFIG_IP1000=mCONFIG_IGB=mCONFIG_IGB_LRO=yCONFIG_NS83820=mCONFIG_HAMACHI=yCONFIG_YELLOWFIN=m
# CONFIG_R8169 is not setCONFIG_SIS190=yCONFIG_SKGE=mCONFIG_SKGE_DEBUG=y
# CONFIG_SKY2 is not set CONFIG_VIA_VELOCITY=mCONFIG_TIGON3=yCONFIG_BNX2=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not setCONFIG_JME=y
# CONFIG_NETDEV_10000 is not set CONFIG_TR=y
# CONFIG_IBMTR is not setCONFIG_IBMOL=m
# CONFIG_IBMLS is not set
# CONFIG_3C359 is not set CONFIG_TMS380TR=mCONFIG_TMSPCI=mCONFIG_ABYSS=mCONFIG_MADGEMC=m
# CONFIG_SMCTR is not set
#
# Wireless LAN
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
# CONFIG_IWLWIFI_LEDS is not set
#
# USB Network Adapters
#CONFIG_USB_CATC=yCONFIG_USB_KAWETH=yCONFIG_USB_PEGASUS=m
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not setCONFIG_USB_HSO=m
# CONFIG_WAN is not setCONFIG_FDDI=yCONFIG_DEFXX=m
# CONFIG_DEFXX_MMIO is not setCONFIG_SKFP=m
# CONFIG_HIPPI is not set
# CONFIG_PPP is not setCONFIG_SLIP=y
# CONFIG_SLIP_COMPRESSED is not setCONFIG_SLIP_SMART=y
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_NET_FC is not setCONFIG_NETCONSOLE=y
# CONFIG_NETCONSOLE_DYNAMIC is not setCONFIG_NETPOLL=y
# CONFIG_NETPOLL_TRAP is not setCONFIG_NET_POLL_CONTROLLER=y
# CONFIG_VIRTIO_NET is not set
# CONFIG_ISDN is not setCONFIG_PHONE=y
#
# Input device support
#CONFIG_INPUT=yCONFIG_INPUT_FF_MEMLESS=yCONFIG_INPUT_POLLDEV=y
#
# Userland interfaces
#CONFIG_INPUT_MOUSEDEV=yCONFIG_INPUT_MOUSEDEV_PSAUX=yCONFIG_INPUT_MOUSEDEV_SCREEN_X=1024CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768CONFIG_INPUT_JOYDEV=y
# CONFIG_INPUT_EVDEV is not setCONFIG_INPUT_EVBUG=y
#
# Input Device Drivers
#CONFIG_INPUT_KEYBOARD=yCONFIG_KEYBOARD_ATKBD=yCONFIG_KEYBOARD_SUNKBD=y
# CONFIG_KEYBOARD_LKKBD is not setCONFIG_KEYBOARD_XTKBD=yCONFIG_KEYBOARD_NEWTON=y
# CONFIG_KEYBOARD_STOWAWAY is not setCONFIG_KEYBOARD_GPIO=mCONFIG_INPUT_MOUSE=y
# CONFIG_MOUSE_PS2 is not setCONFIG_MOUSE_SERIAL=yCONFIG_MOUSE_APPLETOUCH=y
# CONFIG_MOUSE_BCM5974 is not setCONFIG_MOUSE_VSXXXAA=yCONFIG_MOUSE_GPIO=mCONFIG_INPUT_JOYSTICK=yCONFIG_JOYSTICK_ANALOG=mCONFIG_JOYSTICK_A3D=m
# CONFIG_JOYSTICK_ADI is not setCONFIG_JOYSTICK_COBRA=mCONFIG_JOYSTICK_GF2K=m
# CONFIG_JOYSTICK_GRIP is not setCONFIG_JOYSTICK_GRIP_MP=mCONFIG_JOYSTICK_GUILLEMOT=yCONFIG_JOYSTICK_INTERACT=yCONFIG_JOYSTICK_SIDEWINDER=yCONFIG_JOYSTICK_TMDC=y
# CONFIG_JOYSTICK_IFORCE is not set
# CONFIG_JOYSTICK_WARRIOR is not set
# CONFIG_JOYSTICK_MAGELLAN is not set
# CONFIG_JOYSTICK_SPACEORB is not setCONFIG_JOYSTICK_SPACEBALL=yCONFIG_JOYSTICK_STINGER=m
# CONFIG_JOYSTICK_TWIDJOY is not setCONFIG_JOYSTICK_ZHENHUA=yCONFIG_JOYSTICK_JOYDUMP=y
# CONFIG_JOYSTICK_XPAD is not setCONFIG_INPUT_TABLET=y
# CONFIG_TABLET_USB_ACECAD is not setCONFIG_TABLET_USB_AIPTEK=y
# CONFIG_TABLET_USB_GTCO is not set
# CONFIG_TABLET_USB_KBTAB is not set
# CONFIG_TABLET_USB_WACOM is not set
# CONFIG_INPUT_TOUCHSCREEN is not setCONFIG_INPUT_MISC=y
# CONFIG_INPUT_PCSPKR is not setCONFIG_INPUT_APANEL=mCONFIG_INPUT_WISTRON_BTNS=y
# CONFIG_INPUT_ATLAS_BTNS is not set
# CONFIG_INPUT_ATI_REMOTE is not setCONFIG_INPUT_ATI_REMOTE2=y
# CONFIG_INPUT_KEYSPAN_REMOTE is not set
# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_YEALINK is not set
# CONFIG_INPUT_CM109 is not setCONFIG_INPUT_UINPUT=y
#
# Hardware I/O ports
#CONFIG_SERIO=yCONFIG_SERIO_I8042=yCONFIG_SERIO_SERPORT=m
# CONFIG_SERIO_CT82C710 is not setCONFIG_SERIO_PCIPS2=mCONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not setCONFIG_GAMEPORT=yCONFIG_GAMEPORT_NS558=yCONFIG_GAMEPORT_L4=y
# CONFIG_GAMEPORT_EMU10K1 is not setCONFIG_GAMEPORT_FM801=m
#
# Character devices
#CONFIG_VT=y
# CONFIG_CONSOLE_TRANSLATIONS is not setCONFIG_VT_CONSOLE=yCONFIG_HW_CONSOLE=yCONFIG_VT_HW_CONSOLE_BINDING=yCONFIG_DEVKMEM=yCONFIG_SERIAL_NONSTANDARD=yCONFIG_COMPUTONE=y
# CONFIG_ROCKETPORT is not setCONFIG_CYCLADES=yCONFIG_CYZ_INTR=yCONFIG_DIGIEPCA=y
# CONFIG_MOXA_INTELLIO is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_ISI is not set
# CONFIG_SYNCLINK is not setCONFIG_SYNCLINKMP=y
# CONFIG_SYNCLINK_GT is not set
# CONFIG_N_HDLC is not set
# CONFIG_RISCOM8 is not set
# CONFIG_SPECIALIX is not setCONFIG_SX=mCONFIG_RIO=yCONFIG_RIO_OLDPCI=y
# CONFIG_STALDRV is not setCONFIG_NOZOMI=m
#
# Serial drivers
#CONFIG_SERIAL_8250=yCONFIG_SERIAL_8250_CONSOLE=yCONFIG_FIX_EARLYCON_MEM=yCONFIG_SERIAL_8250_PCI=mCONFIG_SERIAL_8250_PNP=yCONFIG_SERIAL_8250_NR_UARTS=4CONFIG_SERIAL_8250_RUNTIME_UARTS=4CONFIG_SERIAL_8250_EXTENDED=yCONFIG_SERIAL_8250_MANY_PORTS=yCONFIG_SERIAL_8250_SHARE_IRQ=y
# CONFIG_SERIAL_8250_DETECT_IRQ is not setCONFIG_SERIAL_8250_RSA=y
# CONFIG_SERIAL_8250_MCA is not set
#
# Non-8250 serial port support
#CONFIG_SERIAL_CORE=yCONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not setCONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not setCONFIG_HVC_DRIVER=yCONFIG_VIRTIO_CONSOLE=yCONFIG_IPMI_HANDLER=yCONFIG_IPMI_PANIC_EVENT=yCONFIG_IPMI_PANIC_STRING=yCONFIG_IPMI_DEVICE_INTERFACE=yCONFIG_IPMI_SI=mCONFIG_IPMI_WATCHDOG=m
# CONFIG_IPMI_POWEROFF is not setCONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_INTEL is not set
# CONFIG_HW_RANDOM_AMD is not setCONFIG_HW_RANDOM_GEODE=m
# CONFIG_HW_RANDOM_VIA is not setCONFIG_HW_RANDOM_VIRTIO=yCONFIG_NVRAM=mCONFIG_R3964=mCONFIG_APPLICOM=mCONFIG_SONYPI=mCONFIG_MWAVE=m
CONFIG_PC8736x_GPIO=yCONFIG_NSC_GPIO=yCONFIG_CS5535_GPIO=m
# CONFIG_RAW_DRIVER is not set
# CONFIG_HPET is not setCONFIG_HANGCHECK_TIMER=yCONFIG_TCG_TPM=mCONFIG_TCG_TIS=m
# CONFIG_TCG_NSC is not setCONFIG_TCG_ATMEL=mCONFIG_TCG_INFINEON=mCONFIG_TELCLOCK=mCONFIG_DEVPORT=yCONFIG_I2C=yCONFIG_I2C_BOARDINFO=yCONFIG_I2C_CHARDEV=yCONFIG_I2C_HELPER_AUTO=yCONFIG_I2C_ALGOBIT=yCONFIG_I2C_ALGOPCA=y
#
# I2C Hardware Bus support
#
#
# PC SMBus host controller drivers
#CONFIG_I2C_ALI1535=y
# CONFIG_I2C_ALI1563 is not setCONFIG_I2C_ALI15X3=yCONFIG_I2C_AMD756=yCONFIG_I2C_AMD8111=yCONFIG_I2C_I801=mCONFIG_I2C_ISCH=y
# CONFIG_I2C_PIIX4 is not setCONFIG_I2C_NFORCE2=yCONFIG_I2C_SIS5595=yCONFIG_I2C_SIS630=y
# CONFIG_I2C_SIS96X is not setCONFIG_I2C_VIA=mCONFIG_I2C_VIAPRO=m
#
# I2C system bus drivers (mostly embedded / system-on-chip) #
# CONFIG_I2C_GPIO is not setCONFIG_I2C_OCORES=yCONFIG_I2C_SIMTEC=y
#
# External I2C/SMBus adapter drivers
#
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_TAOS_EVM is not setCONFIG_I2C_TINY_USB=m
#
# Graphics adapter I2C/DDC channel drivers
#CONFIG_I2C_VOODOO3=m
#
# Other I2C/SMBus bus drivers
#CONFIG_I2C_PCA_PLATFORM=yCONFIG_I2C_STUB=m
# CONFIG_SCx200_ACB is not set
#
# Miscellaneous I2C Chip support
#CONFIG_DS1682=mCONFIG_AT24=mCONFIG_SENSORS_EEPROM=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not setCONFIG_TPS65010=mCONFIG_SENSORS_MAX6875=mCONFIG_SENSORS_TSL2550=yCONFIG_I2C_DEBUG_CORE=yCONFIG_I2C_DEBUG_ALGO=y
# CONFIG_I2C_DEBUG_BUS is not setCONFIG_I2C_DEBUG_CHIP=yCONFIG_SPI=yCONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#CONFIG_SPI_BITBANG=m
#
# SPI Protocol Masters
#
# CONFIG_SPI_AT25 is not set
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not setCONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=yCONFIG_GPIOLIB=yCONFIG_GPIO_SYSFS=y
#
# I2C GPIO expanders:
#CONFIG_GPIO_MAX732X=m
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCF857X is not set
#
# PCI GPIO expanders:
#CONFIG_GPIO_BT8XX=m
#
# SPI GPIO expanders:
#CONFIG_GPIO_MAX7301=mCONFIG_GPIO_MCP23S08=mCONFIG_W1=yCONFIG_W1_CON=y
#
# 1-wire Bus Masters
#CONFIG_W1_MASTER_MATROX=m
# CONFIG_W1_MASTER_DS2490 is not setCONFIG_W1_MASTER_DS2482=m
# CONFIG_W1_MASTER_GPIO is not set
#
# 1-wire Slaves
#CONFIG_W1_SLAVE_THERM=yCONFIG_W1_SLAVE_SMEM=yCONFIG_W1_SLAVE_DS2433=y
# CONFIG_W1_SLAVE_DS2433_CRC is not set
# CONFIG_W1_SLAVE_DS2760 is not setCONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
# CONFIG_PDA_POWER is not set
# CONFIG_BATTERY_DS2760 is not set
# CONFIG_BATTERY_BQ27x00 is not setCONFIG_HWMON=mCONFIG_HWMON_VID=m
# CONFIG_SENSORS_ABITUGURU is not set
# CONFIG_SENSORS_ABITUGURU3 is not set
# CONFIG_SENSORS_AD7414 is not setCONFIG_SENSORS_AD7418=m
# CONFIG_SENSORS_ADCXX is not setCONFIG_SENSORS_ADM1021=mCONFIG_SENSORS_ADM1025=m
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not setCONFIG_SENSORS_ADT7470=mCONFIG_SENSORS_ADT7473=mCONFIG_SENSORS_K8TEMP=mCONFIG_SENSORS_ASB100=mCONFIG_SENSORS_ATXP1=mCONFIG_SENSORS_DS1621=mCONFIG_SENSORS_I5K_AMB=m
# CONFIG_SENSORS_F71805F is not setCONFIG_SENSORS_F71882FG=m
# CONFIG_SENSORS_F75375S is not setCONFIG_SENSORS_FSCHER=mCONFIG_SENSORS_FSCPOS=m
# CONFIG_SENSORS_FSCHMD is not setCONFIG_SENSORS_GL518SM=mCONFIG_SENSORS_GL520SM=m
# CONFIG_SENSORS_CORETEMP is not setCONFIG_SENSORS_IBMAEM=mCONFIG_SENSORS_IBMPEX=mCONFIG_SENSORS_IT87=mCONFIG_SENSORS_LM63=m
# CONFIG_SENSORS_LM70 is not setCONFIG_SENSORS_LM75=m
# CONFIG_SENSORS_LM77 is not setCONFIG_SENSORS_LM78=mCONFIG_SENSORS_LM80=mCONFIG_SENSORS_LM83=mCONFIG_SENSORS_LM85=mCONFIG_SENSORS_LM87=mCONFIG_SENSORS_LM90=mCONFIG_SENSORS_LM92=m
# CONFIG_SENSORS_LM93 is not set
# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX1619 is not setCONFIG_SENSORS_MAX6650=mCONFIG_SENSORS_PC87360=mCONFIG_SENSORS_PC87427=m
# CONFIG_SENSORS_SIS5595 is not setCONFIG_SENSORS_DME1737=m
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_SMSC47M192 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
# CONFIG_SENSORS_ADS7828 is not setCONFIG_SENSORS_THMC50=mCONFIG_SENSORS_VIA686A=mCONFIG_SENSORS_VT1211=mCONFIG_SENSORS_VT8231=mCONFIG_SENSORS_W83781D=m
# CONFIG_SENSORS_W83791D is not set
# CONFIG_SENSORS_W83792D is not setCONFIG_SENSORS_W83793=mCONFIG_SENSORS_W83L785TS=mCONFIG_SENSORS_W83L786NG=mCONFIG_SENSORS_W83627HF=m
# CONFIG_SENSORS_W83627EHF is not setCONFIG_SENSORS_HDAPS=m
# CONFIG_SENSORS_APPLESMC is not set
# CONFIG_HWMON_DEBUG_CHIP is not setCONFIG_THERMAL=yCONFIG_WATCHDOG=yCONFIG_WATCHDOG_NOWAYOUT=y
#
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
# CONFIG_ACQUIRE_WDT is not set
# CONFIG_ADVANTECH_WDT is not setCONFIG_ALIM1535_WDT=y
# CONFIG_ALIM7101_WDT is not setCONFIG_SC520_WDT=yCONFIG_IB700_WDT=yCONFIG_IBMASR=y
# CONFIG_WAFER_WDT is not setCONFIG_I6300ESB_WDT=yCONFIG_ITCO_WDT=y
# CONFIG_ITCO_VENDOR_SUPPORT is not set
# CONFIG_IT8712F_WDT is not setCONFIG_IT87_WDT=m
# CONFIG_HP_WATCHDOG is not setCONFIG_SC1200_WDT=mCONFIG_PC87413_WDT=yCONFIG_RDC321X_WDT=mCONFIG_60XX_WDT=yCONFIG_SBC8360_WDT=yCONFIG_SBC7240_WDT=y
# CONFIG_CPU5_WDT is not set
# CONFIG_SMSC37B787_WDT is not setCONFIG_W83627HF_WDT=yCONFIG_W83697HF_WDT=mCONFIG_W83697UG_WDT=y
# CONFIG_W83877F_WDT is not setCONFIG_W83977F_WDT=mCONFIG_MACHZ_WDT=mCONFIG_SBC_EPX_C3_WATCHDOG=m
#
# PCI-based Watchdog Cards
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
#
# USB-based Watchdog Cards
#CONFIG_USBPCWATCHDOG=y
#
# Sonics Silicon Backplane
#CONFIG_SSB_POSSIBLE=yCONFIG_SSB=yCONFIG_SSB_SPROM=yCONFIG_SSB_PCIHOST_POSSIBLE=yCONFIG_SSB_PCIHOST=y
# CONFIG_SSB_B43_PCI_BRIDGE is not setCONFIG_SSB_SILENT=yCONFIG_SSB_DRIVER_PCICORE_POSSIBLE=yCONFIG_SSB_DRIVER_PCICORE=y
#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not setCONFIG_MFD_SM501=y
# CONFIG_MFD_SM501_GPIO is not setCONFIG_HTC_PASIC3=m
# CONFIG_MFD_TMIO is not setCONFIG_PMIC_DA903X=y
# CONFIG_MFD_WM8400 is not set
#
# Voltage and Current regulators
#CONFIG_REGULATOR=y
# CONFIG_REGULATOR_DEBUG is not set
# CONFIG_REGULATOR_FIXED_VOLTAGE is not setCONFIG_REGULATOR_VIRTUAL_CONSUMER=yCONFIG_REGULATOR_BQ24022=yCONFIG_REGULATOR_DA903X=y
#
# Multimedia devices
#
#
# Multimedia core support
#
# CONFIG_VIDEO_DEV is not setCONFIG_DVB_CORE=yCONFIG_VIDEO_MEDIA=y
#
# Multimedia drivers
#
# CONFIG_MEDIA_ATTACH is not setCONFIG_MEDIA_TUNER=yCONFIG_MEDIA_TUNER_CUSTOMIZE=yCONFIG_MEDIA_TUNER_SIMPLE=mCONFIG_MEDIA_TUNER_TDA8290=yCONFIG_MEDIA_TUNER_TDA827X=yCONFIG_MEDIA_TUNER_TDA18271=yCONFIG_MEDIA_TUNER_TDA9887=yCONFIG_MEDIA_TUNER_TEA5761=mCONFIG_MEDIA_TUNER_TEA5767=yCONFIG_MEDIA_TUNER_MT20XX=m
# CONFIG_MEDIA_TUNER_MT2060 is not set
# CONFIG_MEDIA_TUNER_MT2266 is not set
# CONFIG_MEDIA_TUNER_MT2131 is not setCONFIG_MEDIA_TUNER_QT1010=m
# CONFIG_MEDIA_TUNER_XC2028 is not setCONFIG_MEDIA_TUNER_XC5000=m
# CONFIG_MEDIA_TUNER_MXL5005S is not setCONFIG_MEDIA_TUNER_MXL5007T=yCONFIG_DVB_CAPTURE_DRIVERS=y
#
# Supported SAA7146 based PCI Adapters
#
# CONFIG_TTPCI_EEPROM is not set
# CONFIG_DVB_BUDGET_CORE is not set
#
# Supported USB Adapters
#CONFIG_DVB_USB=mCONFIG_DVB_USB_DEBUG=yCONFIG_DVB_USB_A800=m
# CONFIG_DVB_USB_DIBUSB_MB is not set
# CONFIG_DVB_USB_DIBUSB_MC is not setCONFIG_DVB_USB_DIB0700=mCONFIG_DVB_USB_UMT_010=mCONFIG_DVB_USB_CXUSB=mCONFIG_DVB_USB_M920X=mCONFIG_DVB_USB_GL861=mCONFIG_DVB_USB_AU6610=mCONFIG_DVB_USB_DIGITV=mCONFIG_DVB_USB_VP7045=mCONFIG_DVB_USB_VP702X=mCONFIG_DVB_USB_GP8PSK=m
# CONFIG_DVB_USB_NOVA_T_USB2 is not set
# CONFIG_DVB_USB_TTUSB2 is not setCONFIG_DVB_USB_DTT200U=mCONFIG_DVB_USB_OPERA1=mCONFIG_DVB_USB_DW2102=mCONFIG_DVB_USB_CINERGY_T2=mCONFIG_DVB_USB_ANYSEE=mCONFIG_DVB_USB_DTV5100=m
# CONFIG_DVB_USB_AF9015 is not setCONFIG_DVB_TTUSB_BUDGET=m
# CONFIG_DVB_TTUSB_DEC is not setCONFIG_DVB_SIANO_SMS1XXX=y
# CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS is not set
#
# Supported FlexCopII (B2C2) Adapters
#
# CONFIG_DVB_B2C2_FLEXCOP is not set
#
# Supported BT878 Adapters
#
#
# Supported Pluto2 Adapters
#CONFIG_DVB_PLUTO2=m
#
# Supported SDMC DM1105 Adapters
#
#
# Supported DVB Frontends
#
#
# Customise DVB Frontends
#CONFIG_DVB_FE_CUSTOMISE=y
#
# DVB-S (satellite) frontends
#CONFIG_DVB_CX24110=m
# CONFIG_DVB_CX24123 is not set
# CONFIG_DVB_MT312 is not setCONFIG_DVB_S5H1420=mCONFIG_DVB_STV0288=y
# CONFIG_DVB_STB6000 is not setCONFIG_DVB_STV0299=mCONFIG_DVB_TDA8083=yCONFIG_DVB_TDA10086=m
# CONFIG_DVB_VES1X93 is not set
# CONFIG_DVB_TUNER_ITD1000 is not set
# CONFIG_DVB_TDA826X is not setCONFIG_DVB_TUA6100=mCONFIG_DVB_CX24116=y
# CONFIG_DVB_SI21XX is not set
#
# DVB-T (terrestrial) frontends
#
# CONFIG_DVB_SP8870 is not setCONFIG_DVB_SP887X=m
# CONFIG_DVB_CX22700 is not setCONFIG_DVB_CX22702=yCONFIG_DVB_DRX397XD=m
# CONFIG_DVB_L64781 is not setCONFIG_DVB_TDA1004X=m
# CONFIG_DVB_NXT6000 is not set
# CONFIG_DVB_MT352 is not set
# CONFIG_DVB_ZL10353 is not set
# CONFIG_DVB_DIB3000MB is not setCONFIG_DVB_DIB3000MC=mCONFIG_DVB_DIB7000M=mCONFIG_DVB_DIB7000P=mCONFIG_DVB_TDA10048=y
#
# DVB-C (cable) frontends
#CONFIG_DVB_VES1820=m
# CONFIG_DVB_TDA10021 is not setCONFIG_DVB_TDA10023=y
# CONFIG_DVB_STV0297 is not set
#
# ATSC (North American/Korean Terrestrial/Cable DTV) frontends #
# CONFIG_DVB_NXT200X is not setCONFIG_DVB_OR51211=y
# CONFIG_DVB_OR51132 is not set
# CONFIG_DVB_BCM3510 is not set CONFIG_DVB_LGDT330X=y
# CONFIG_DVB_S5H1409 is not set
# CONFIG_DVB_AU8522 is not setCONFIG_DVB_S5H1411=m
#
# Digital terrestrial only tuners/PLL
#CONFIG_DVB_PLL=mCONFIG_DVB_TUNER_DIB0070=y
#
# SEC control devices for DVB-S
#CONFIG_DVB_LNBP21=mCONFIG_DVB_ISL6405=mCONFIG_DVB_ISL6421=mCONFIG_DVB_LGS8GL5=y
#
# Tools to develop new frontends
#
# CONFIG_DVB_DUMMY_FE is not setCONFIG_DVB_AF9013=yCONFIG_DAB=y
# CONFIG_USB_DABUSB is not set
#
# Graphics support
#CONFIG_AGP=yCONFIG_AGP_ALI=mCONFIG_AGP_ATI=yCONFIG_AGP_AMD=mCONFIG_AGP_AMD64=mCONFIG_AGP_INTEL=yCONFIG_AGP_NVIDIA=m
# CONFIG_AGP_SIS is not setCONFIG_AGP_SWORKS=y
# CONFIG_AGP_VIA is not setCONFIG_AGP_EFFICEON=mCONFIG_DRM=yCONFIG_DRM_TDFX=mCONFIG_DRM_R128=y
# CONFIG_DRM_RADEON is not set
# CONFIG_DRM_I810 is not set
# CONFIG_DRM_I830 is not set
# CONFIG_DRM_I915 is not setCONFIG_DRM_MGA=y
# CONFIG_DRM_SIS is not setCONFIG_DRM_VIA=mCONFIG_DRM_SAVAGE=yCONFIG_VGASTATE=y
# CONFIG_VIDEO_OUTPUT_CONTROL is not setCONFIG_FB=yCONFIG_FIRMWARE_EDID=yCONFIG_FB_DDC=yCONFIG_FB_BOOT_VESA_SUPPORT=yCONFIG_FB_CFB_FILLRECT=yCONFIG_FB_CFB_COPYAREA=yCONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not setCONFIG_FB_SYS_FILLRECT=yCONFIG_FB_SYS_COPYAREA=yCONFIG_FB_SYS_IMAGEBLIT=y
# CONFIG_FB_FOREIGN_ENDIAN is not setCONFIG_FB_SYS_FOPS=yCONFIG_FB_DEFERRED_IO=yCONFIG_FB_HECUBA=yCONFIG_FB_SVGALIB=m
# CONFIG_FB_MACMODES is not setCONFIG_FB_BACKLIGHT=yCONFIG_FB_MODE_HELPERS=yCONFIG_FB_TILEBLITTING=y
#
# Frame buffer hardware drivers
#CONFIG_FB_PM2=mCONFIG_FB_PM2_FIFO_DISCONNECT=yCONFIG_FB_CYBER2000=m
# CONFIG_FB_ARC is not setCONFIG_FB_IMSTT=yCONFIG_FB_UVESA=m
# CONFIG_FB_EFI is not setCONFIG_FB_N411=yCONFIG_FB_HGA=y
# CONFIG_FB_HGA_ACCEL is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not setCONFIG_FB_I810=yCONFIG_FB_I810_GTF=yCONFIG_FB_I810_I2C=yCONFIG_FB_LE80578=m
# CONFIG_FB_CARILLO_RANCH is not set
# CONFIG_FB_INTEL is not setCONFIG_FB_MATROX=y
# CONFIG_FB_MATROX_MILLENIUM is not setCONFIG_FB_MATROX_MYSTIQUE=y
# CONFIG_FB_MATROX_G is not setCONFIG_FB_MATROX_I2C=mCONFIG_FB_MATROX_MULTIHEAD=yCONFIG_FB_ATY128=m
# CONFIG_FB_ATY128_BACKLIGHT is not setCONFIG_FB_ATY=mCONFIG_FB_ATY_CT=y
# CONFIG_FB_ATY_GENERIC_LCD is not setCONFIG_FB_ATY_GX=yCONFIG_FB_ATY_BACKLIGHT=yCONFIG_FB_S3=mCONFIG_FB_SAVAGE=mCONFIG_FB_SAVAGE_I2C=y
# CONFIG_FB_SAVAGE_ACCEL is not setCONFIG_FB_SIS=y
# CONFIG_FB_SIS_300 is not setCONFIG_FB_SIS_315=yCONFIG_FB_VIA=mCONFIG_FB_NEOMAGIC=m
# CONFIG_FB_KYRO is not setCONFIG_FB_3DFX=m
# CONFIG_FB_3DFX_ACCEL is not setCONFIG_FB_VOODOO1=y
# CONFIG_FB_VT8623 is not set
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_ARK is not setCONFIG_FB_PM3=yCONFIG_FB_CARMINE=mCONFIG_FB_CARMINE_DRAM_EVAL=y
# CONFIG_CARMINE_DRAM_CUSTOM is not setCONFIG_FB_GEODE=yCONFIG_FB_GEODE_LX=y
# CONFIG_FB_GEODE_GX is not setCONFIG_FB_GEODE_GX1=yCONFIG_FB_SM501=yCONFIG_FB_METRONOME=yCONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not setCONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_BACKLIGHT_CORGI is not set
# CONFIG_BACKLIGHT_PROGEAR is not setCONFIG_BACKLIGHT_DA903X=yCONFIG_BACKLIGHT_MBP_NVIDIA=yCONFIG_BACKLIGHT_SAHARA=m
#
# Display device support
#CONFIG_DISPLAY_SUPPORT=y
#
# Display hardware drivers
#
#
# Console display driver support
#CONFIG_VGA_CONSOLE=yCONFIG_VGACON_SOFT_SCROLLBACK=yCONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64CONFIG_DUMMY_CONSOLE=y
CONFIG_FONT_8x16=y
# CONFIG_LOGO is not set
# CONFIG_SOUND is not setCONFIG_HID_SUPPORT=yCONFIG_HID=y
# CONFIG_HID_DEBUG is not set
# CONFIG_HIDRAW is not set
#
# USB Input Devices
#CONFIG_USB_HID=yCONFIG_HID_PID=yCONFIG_USB_HIDDEV=yCONFIG_USB_MOUSE=y
#
# Special HID drivers
#
# CONFIG_HID_COMPAT is not setCONFIG_HID_A4TECH=y
# CONFIG_HID_APPLE is not set
# CONFIG_HID_BELKIN is not setCONFIG_HID_BRIGHT=mCONFIG_HID_CHERRY=yCONFIG_HID_CHICONY=y
# CONFIG_HID_CYPRESS is not setCONFIG_HID_DELL=mCONFIG_HID_EZKEY=yCONFIG_HID_GYRATION=y
# CONFIG_HID_LOGITECH is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not setCONFIG_HID_PANTHERLORD=y
# CONFIG_PANTHERLORD_FF is not setCONFIG_HID_PETALYNX=mCONFIG_HID_SAMSUNG=y
# CONFIG_HID_SONY is not setCONFIG_HID_SUNPLUS=y
# CONFIG_THRUSTMASTER_FF is not setCONFIG_ZEROPLUS_FF=yCONFIG_USB_SUPPORT=yCONFIG_USB_ARCH_HAS_HCD=yCONFIG_USB_ARCH_HAS_OHCI=yCONFIG_USB_ARCH_HAS_EHCI=yCONFIG_USB=yCONFIG_USB_DEBUG=y
# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
#
# Miscellaneous USB options
#CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not setCONFIG_USB_DYNAMIC_MINORS=y
# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not setCONFIG_USB_OTG_BLACKLIST_HUB=y
# CONFIG_USB_MON is not set
# CONFIG_USB_WUSB is not setCONFIG_USB_WUSB_CBAF=yCONFIG_USB_WUSB_CBAF_DEBUG=y
#
# USB Host Controller Drivers
#
# CONFIG_USB_C67X00_HCD is not setCONFIG_USB_EHCI_HCD=yCONFIG_USB_EHCI_ROOT_HUB_TT=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not setCONFIG_USB_OHCI_HCD=y
# CONFIG_USB_OHCI_HCD_SSB is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not setCONFIG_USB_OHCI_LITTLE_ENDIAN=yCONFIG_USB_UHCI_HCD=yCONFIG_USB_SL811_HCD=mCONFIG_USB_R8A66597_HCD=y
# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
#CONFIG_USB_ACM=y
# CONFIG_USB_PRINTER is not setCONFIG_USB_WDM=m
# CONFIG_USB_TMC is not set
#
# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' #
#
# may also be needed; see USB_STORAGE Help for more information # # CONFIG_USB_STORAGE is not set CONFIG_USB_LIBUSUAL=y
#
# USB Imaging devices
#CONFIG_USB_MDC800=mCONFIG_USB_MICROTEK=y
#
# USB port drivers
#
# CONFIG_USB_SERIAL is not set
#
# USB Miscellaneous drivers
#CONFIG_USB_EMI62=m
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
# CONFIG_USB_SEVSEG is not setCONFIG_USB_RIO500=y
# CONFIG_USB_LEGOTOWER is not setCONFIG_USB_LCD=mCONFIG_USB_BERRY_CHARGE=mCONFIG_USB_LED=yCONFIG_USB_CYPRESS_CY7C63=yCONFIG_USB_CYTHERM=mCONFIG_USB_PHIDGET=yCONFIG_USB_PHIDGETKIT=yCONFIG_USB_PHIDGETMOTORCONTROL=yCONFIG_USB_PHIDGETSERVO=y
# CONFIG_USB_IDMOUSE is not set
# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not setCONFIG_USB_SISUSBVGA=yCONFIG_USB_SISUSBVGA_CON=y
# CONFIG_USB_LD is not set
# CONFIG_USB_TRANCEVIBRATOR is not setCONFIG_USB_IOWARRIOR=y
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not setCONFIG_USB_VST=yCONFIG_UWB=yCONFIG_UWB_HWA=mCONFIG_UWB_WHCI=yCONFIG_UWB_WLP=yCONFIG_UWB_I1480U=mCONFIG_UWB_I1480U_WLP=mCONFIG_MMC=mCONFIG_MMC_DEBUG=yCONFIG_MMC_UNSAFE_RESUME=y
#
# MMC/SD/SDIO Card Drivers
#CONFIG_MMC_BLOCK=mCONFIG_MMC_BLOCK_BOUNCE=yCONFIG_SDIO_UART=mCONFIG_MMC_TEST=m
#
# MMC/SD/SDIO Host Controller Drivers
#CONFIG_MMC_SDHCI=mCONFIG_MMC_SDHCI_PCI=mCONFIG_MMC_RICOH_MMC=mCONFIG_MMC_WBSD=m
# CONFIG_MMC_TIFM_SD is not setCONFIG_MEMSTICK=y
# CONFIG_MEMSTICK_DEBUG is not set
#
# MemoryStick drivers
#CONFIG_MEMSTICK_UNSAFE_RESUME=yCONFIG_MSPRO_BLOCK=y
#
# MemoryStick Host Controller Drivers
#CONFIG_MEMSTICK_TIFM_MS=mCONFIG_MEMSTICK_JMICRON_38X=yCONFIG_NEW_LEDS=yCONFIG_LEDS_CLASS=y
#
# LED drivers
#CONFIG_LEDS_PCA9532=yCONFIG_LEDS_GPIO=mCONFIG_LEDS_HP_DISK=y
# CONFIG_LEDS_PCA955X is not setCONFIG_LEDS_DA903X=y
#
# LED Triggers
#CONFIG_LEDS_TRIGGERS=yCONFIG_LEDS_TRIGGER_TIMER=yCONFIG_LEDS_TRIGGER_HEARTBEAT=mCONFIG_LEDS_TRIGGER_BACKLIGHT=y
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not setCONFIG_EDAC=y
#
# Reporting subsystems
#
# CONFIG_EDAC_DEBUG is not set
# CONFIG_EDAC_MM_EDAC is not setCONFIG_RTC_LIB=mCONFIG_RTC_CLASS=m
#
# RTC interfaces
#CONFIG_RTC_INTF_SYSFS=y
# CONFIG_RTC_INTF_PROC is not setCONFIG_RTC_INTF_DEV=yCONFIG_RTC_INTF_DEV_UIE_EMUL=y
# CONFIG_RTC_DRV_TEST is not set
#
# I2C RTC drivers
#CONFIG_RTC_DRV_DS1307=m
# CONFIG_RTC_DRV_DS1374 is not setCONFIG_RTC_DRV_DS1672=mCONFIG_RTC_DRV_MAX6900=mCONFIG_RTC_DRV_RS5C372=mCONFIG_RTC_DRV_ISL1208=mCONFIG_RTC_DRV_X1205=mCONFIG_RTC_DRV_PCF8563=mCONFIG_RTC_DRV_PCF8583=mCONFIG_RTC_DRV_M41T80=m
# CONFIG_RTC_DRV_M41T80_WDT is not setCONFIG_RTC_DRV_S35390A=m
# CONFIG_RTC_DRV_FM3130 is not set
#
# SPI RTC drivers
#CONFIG_RTC_DRV_M41T94=mCONFIG_RTC_DRV_DS1305=m
# CONFIG_RTC_DRV_MAX6902 is not setCONFIG_RTC_DRV_R9701=mCONFIG_RTC_DRV_RS5C348=m
# CONFIG_RTC_DRV_DS3234 is not set
#
# Platform RTC drivers
#CONFIG_RTC_DRV_CMOS=mCONFIG_RTC_DRV_DS1286=mCONFIG_RTC_DRV_DS1511=m
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not setCONFIG_RTC_DRV_STK17TA8=mCONFIG_RTC_DRV_M48T86=mCONFIG_RTC_DRV_M48T35=mCONFIG_RTC_DRV_M48T59=m
# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
# CONFIG_DMADEVICES is not setCONFIG_UIO=yCONFIG_UIO_CIF=yCONFIG_UIO_PDRV=yCONFIG_UIO_PDRV_GENIRQ=yCONFIG_UIO_SMX=yCONFIG_UIO_SERCOS3=y
#
# Firmware Drivers
#
# CONFIG_EDD is not set
# CONFIG_FIRMWARE_MEMMAP is not set
# CONFIG_EFI_VARS is not setCONFIG_DELL_RBU=y
# CONFIG_DCDBAS is not setCONFIG_ISCSI_IBFT_FIND=y
# CONFIG_ISCSI_IBFT is not set
#
# File systems
#CONFIG_EXT2_FS=yCONFIG_EXT2_FS_XATTR=yCONFIG_EXT2_FS_POSIX_ACL=yCONFIG_EXT2_FS_SECURITY=yCONFIG_EXT2_FS_XIP=yCONFIG_EXT3_FS=yCONFIG_EXT3_FS_XATTR=yCONFIG_EXT3_FS_POSIX_ACL=yCONFIG_EXT3_FS_SECURITY=yCONFIG_EXT4_FS=y
# CONFIG_EXT4DEV_COMPAT is not setCONFIG_EXT4_FS_XATTR=y
# CONFIG_EXT4_FS_POSIX_ACL is not setCONFIG_EXT4_FS_SECURITY=yCONFIG_FS_XIP=yCONFIG_JBD=yCONFIG_JBD_DEBUG=yCONFIG_JBD2=y
# CONFIG_JBD2_DEBUG is not setCONFIG_FS_MBCACHE=yCONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not setCONFIG_REISERFS_PROC_INFO=yCONFIG_REISERFS_FS_XATTR=yCONFIG_REISERFS_FS_POSIX_ACL=yCONFIG_REISERFS_FS_SECURITY=y
# CONFIG_JFS_FS is not setCONFIG_FS_POSIX_ACL=yCONFIG_FILE_LOCKING=yCONFIG_XFS_FS=y
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_POSIX_ACL is not setCONFIG_XFS_RT=yCONFIG_XFS_DEBUG=y
# CONFIG_GFS2_FS is not setCONFIG_OCFS2_FS=y
# CONFIG_OCFS2_FS_O2CB is not setCONFIG_OCFS2_FS_USERSPACE_CLUSTER=yCONFIG_OCFS2_FS_STATS=yCONFIG_OCFS2_DEBUG_MASKLOG=yCONFIG_OCFS2_DEBUG_FS=y
# CONFIG_OCFS2_COMPAT_JBD is not set
# CONFIG_DNOTIFY is not setCONFIG_INOTIFY=yCONFIG_INOTIFY_USER=yCONFIG_QUOTA=yCONFIG_QUOTA_NETLINK_INTERFACE=yCONFIG_PRINT_QUOTA_WARNING=yCONFIG_QFMT_V1=yCONFIG_QFMT_V2=yCONFIG_QUOTACTL=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not setCONFIG_FUSE_FS=m
#
# CD-ROM/DVD Filesystems
#
# CONFIG_ISO9660_FS is not setCONFIG_UDF_FS=mCONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
#CONFIG_FAT_FS=yCONFIG_MSDOS_FS=mCONFIG_VFAT_FS=yCONFIG_FAT_DEFAULT_CODEPAGE=437CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#CONFIG_PROC_FS=yCONFIG_PROC_KCORE=y
# CONFIG_PROC_VMCORE is not setCONFIG_PROC_SYSCTL=y
# CONFIG_PROC_PAGE_MONITOR is not setCONFIG_SYSFS=yCONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not setCONFIG_HUGETLBFS=yCONFIG_HUGETLB_PAGE=yCONFIG_CONFIGFS_FS=y
#
# Miscellaneous filesystems
#CONFIG_ADFS_FS=m
# CONFIG_ADFS_FS_RW is not setCONFIG_AFFS_FS=y
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not setCONFIG_BFS_FS=m
# CONFIG_EFS_FS is not set
# CONFIG_CRAMFS is not setCONFIG_VXFS_FS=mCONFIG_MINIX_FS=yCONFIG_OMFS_FS=m
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not setCONFIG_ROMFS_FS=mCONFIG_SYSV_FS=yCONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not setCONFIG_UFS_DEBUG=y
# CONFIG_NETWORK_FILESYSTEMS is not set
#
# Partition Types
#CONFIG_PARTITION_ADVANCED=yCONFIG_ACORN_PARTITION=yCONFIG_ACORN_PARTITION_CUMANA=yCONFIG_ACORN_PARTITION_EESOX=yCONFIG_ACORN_PARTITION_ICS=yCONFIG_ACORN_PARTITION_ADFS=yCONFIG_ACORN_PARTITION_POWERTEC=yCONFIG_ACORN_PARTITION_RISCIX=y
# CONFIG_OSF_PARTITION is not setCONFIG_AMIGA_PARTITION=yCONFIG_ATARI_PARTITION=y
# CONFIG_MAC_PARTITION is not setCONFIG_MSDOS_PARTITION=yCONFIG_BSD_DISKLABEL=y
# CONFIG_MINIX_SUBPARTITION is not setCONFIG_SOLARIS_X86_PARTITION=yCONFIG_UNIXWARE_DISKLABEL=y
# CONFIG_LDM_PARTITION is not setCONFIG_SGI_PARTITION=yCONFIG_ULTRIX_PARTITION=yCONFIG_SUN_PARTITION=y
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not setCONFIG_SYSV68_PARTITION=yCONFIG_NLS=yCONFIG_NLS_DEFAULT="iso8859-1"CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not setCONFIG_NLS_CODEPAGE_850=mCONFIG_NLS_CODEPAGE_852=yCONFIG_NLS_CODEPAGE_855=yCONFIG_NLS_CODEPAGE_857=yCONFIG_NLS_CODEPAGE_860=yCONFIG_NLS_CODEPAGE_861=yCONFIG_NLS_CODEPAGE_862=y
# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not setCONFIG_NLS_CODEPAGE_865=mCONFIG_NLS_CODEPAGE_866=yCONFIG_NLS_CODEPAGE_869=yCONFIG_NLS_CODEPAGE_936=yCONFIG_NLS_CODEPAGE_950=yCONFIG_NLS_CODEPAGE_932=mCONFIG_NLS_CODEPAGE_949=m
# CONFIG_NLS_CODEPAGE_874 is not set
# CONFIG_NLS_ISO8859_8 is not setCONFIG_NLS_CODEPAGE_1250=mCONFIG_NLS_CODEPAGE_1251=mCONFIG_NLS_ASCII=yCONFIG_NLS_ISO8859_1=yCONFIG_NLS_ISO8859_2=mCONFIG_NLS_ISO8859_3=yCONFIG_NLS_ISO8859_4=yCONFIG_NLS_ISO8859_5=yCONFIG_NLS_ISO8859_6=yCONFIG_NLS_ISO8859_7=mCONFIG_NLS_ISO8859_9=yCONFIG_NLS_ISO8859_13=yCONFIG_NLS_ISO8859_14=yCONFIG_NLS_ISO8859_15=yCONFIG_NLS_KOI8_R=mCONFIG_NLS_KOI8_U=m
# CONFIG_NLS_UTF8 is not setCONFIG_DLM=y
# CONFIG_DLM_DEBUG is not set
#
# Kernel hacking
#CONFIG_TRACE_IRQFLAGS_SUPPORT=yCONFIG_PRINTK_TIME=yCONFIG_ALLOW_WARNINGS=y
# CONFIG_ENABLE_WARN_DEPRECATED is not setCONFIG_ENABLE_MUST_CHECK=yCONFIG_FRAME_WARN=1024CONFIG_MAGIC_SYSRQ=yCONFIG_UNUSED_SYMBOLS=yCONFIG_DEBUG_FS=yCONFIG_HEADERS_CHECK=y
# CONFIG_DEBUG_KERNEL is not setCONFIG_SCHED_DEBUG=yCONFIG_SCHEDSTATS=yCONFIG_STACKTRACE=y
# CONFIG_DEBUG_BUGVERBOSE is not setCONFIG_DEBUG_MEMORY_INIT=yCONFIG_FRAME_POINTER=yCONFIG_RCU_CPU_STALL_DETECTOR=yCONFIG_LATENCYTOP=yCONFIG_SYSCTL_SYSCALL_CHECK=yCONFIG_DEBUG_PER_CPU_MAPS=yCONFIG_HAVE_FUNCTION_TRACER=yCONFIG_HAVE_DYNAMIC_FTRACE=yCONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
#
# Tracers
#
# CONFIG_SYSPROF_TRACER is not set
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not setCONFIG_BUILD_DOCSRC=yCONFIG_DYNAMIC_PRINTK_DEBUG=yCONFIG_SAMPLES=y
# CONFIG_SAMPLE_KOBJECT is not setCONFIG_SAMPLE_KPROBES=mCONFIG_SAMPLE_KRETPROBES=mCONFIG_HAVE_ARCH_KGDB=yCONFIG_STRICT_DEVMEM=y
# CONFIG_X86_VERBOSE_BOOTUP is not setCONFIG_EARLY_PRINTK=yCONFIG_EARLY_PRINTK_DBGP=yCONFIG_4KSTACKS=yCONFIG_DOUBLEFAULT=yCONFIG_IO_DELAY_TYPE_0X80=0CONFIG_IO_DELAY_TYPE_0XED=1CONFIG_IO_DELAY_TYPE_UDELAY=2CONFIG_IO_DELAY_TYPE_NONE=3CONFIG_IO_DELAY_0X80=y
# CONFIG_IO_DELAY_0XED is not set
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not setCONFIG_DEFAULT_IO_DELAY_TYPE=0
# CONFIG_OPTIMIZE_INLINING is not set
#
# Security options
#
# CONFIG_KEYS is not setCONFIG_SECURITY=yCONFIG_SECURITYFS=yCONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK_XFRM=y
# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX_BOOTPARAM=y CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 CONFIG_SECURITY_SELINUX_DISABLE=y
# CONFIG_SECURITY_SELINUX_DEVELOP is not set CONFIG_SECURITY_SELINUX_AVC_STATS=y CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX=y CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE=19 CONFIG_CRYPTO=y
#
# Crypto core or helper
#CONFIG_CRYPTO_FIPS=yCONFIG_CRYPTO_ALGAPI=yCONFIG_CRYPTO_AEAD=yCONFIG_CRYPTO_BLKCIPHER=yCONFIG_CRYPTO_HASH=yCONFIG_CRYPTO_RNG=yCONFIG_CRYPTO_MANAGER=yCONFIG_CRYPTO_GF128MUL=y
# CONFIG_CRYPTO_NULL is not setCONFIG_CRYPTO_CRYPTD=mCONFIG_CRYPTO_AUTHENC=yCONFIG_CRYPTO_TEST=m
#
# Authenticated Encryption with Associated Data
#
# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_GCM is not setCONFIG_CRYPTO_SEQIV=m
#
# Block modes
#CONFIG_CRYPTO_CBC=yCONFIG_CRYPTO_CTR=m
# CONFIG_CRYPTO_CTS is not setCONFIG_CRYPTO_ECB=mCONFIG_CRYPTO_LRW=mCONFIG_CRYPTO_PCBC=yCONFIG_CRYPTO_XTS=y
#
# Hash modes
#CONFIG_CRYPTO_HMAC=yCONFIG_CRYPTO_XCBC=y
#
# Digest
#CONFIG_CRYPTO_CRC32C=yCONFIG_CRYPTO_CRC32C_INTEL=yCONFIG_CRYPTO_MD4=mCONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not setCONFIG_CRYPTO_RMD128=yCONFIG_CRYPTO_RMD160=mCONFIG_CRYPTO_RMD256=m
# CONFIG_CRYPTO_RMD320 is not setCONFIG_CRYPTO_SHA1=yCONFIG_CRYPTO_SHA256=mCONFIG_CRYPTO_SHA512=mCONFIG_CRYPTO_TGR192=m
# CONFIG_CRYPTO_WP512 is not set
#
# Ciphers
#CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_AES_586 is not setCONFIG_CRYPTO_ANUBIS=y
# CONFIG_CRYPTO_ARC4 is not setCONFIG_CRYPTO_BLOWFISH=yCONFIG_CRYPTO_CAMELLIA=y
# CONFIG_CRYPTO_CAST5 is not setCONFIG_CRYPTO_CAST6=yCONFIG_CRYPTO_DES=yCONFIG_CRYPTO_FCRYPT=m
# CONFIG_CRYPTO_KHAZAD is not setCONFIG_CRYPTO_SALSA20=m
# CONFIG_CRYPTO_SALSA20_586 is not setCONFIG_CRYPTO_SEED=yCONFIG_CRYPTO_SERPENT=y
# CONFIG_CRYPTO_TEA is not setCONFIG_CRYPTO_TWOFISH=yCONFIG_CRYPTO_TWOFISH_COMMON=yCONFIG_CRYPTO_TWOFISH_586=m
#
# Compression
#CONFIG_CRYPTO_DEFLATE=yCONFIG_CRYPTO_LZO=m
#
# Random Number Generation
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
# CONFIG_CRYPTO_HW is not setCONFIG_HAVE_KVM=yCONFIG_VIRTUALIZATION=yCONFIG_KVM=yCONFIG_KVM_INTEL=yCONFIG_KVM_AMD=mCONFIG_LGUEST=yCONFIG_VIRTIO=yCONFIG_VIRTIO_RING=yCONFIG_VIRTIO_PCI=m
# CONFIG_VIRTIO_BALLOON is not set
#
# Library routines
#CONFIG_BITREVERSE=yCONFIG_GENERIC_FIND_FIRST_BIT=yCONFIG_GENERIC_FIND_NEXT_BIT=yCONFIG_CRC_CCITT=yCONFIG_CRC16=yCONFIG_CRC_T10DIF=yCONFIG_CRC_ITU_T=yCONFIG_CRC32=yCONFIG_CRC7=mCONFIG_LIBCRC32C=yCONFIG_AUDIT_GENERIC=yCONFIG_ZLIB_INFLATE=yCONFIG_ZLIB_DEFLATE=yCONFIG_LZO_COMPRESS=mCONFIG_LZO_DECOMPRESS=mCONFIG_TEXTSEARCH=yCONFIG_TEXTSEARCH_KMP=yCONFIG_TEXTSEARCH_BM=yCONFIG_TEXTSEARCH_FSM=yCONFIG_PLIST=yCONFIG_HAS_IOMEM=yCONFIG_HAS_IOPORT=yCONFIG_HAS_DMA=yCONFIG_CHECK_SIGNATURE=yCONFIG_FORCE_SUCCESSFUL_BUILD=yCONFIG_FORCE_MINIMAL_CONFIG=yCONFIG_FORCE_MINIMAL_CONFIG_PHYS=yCONFIG_X86_32_ALWAYS_ON=y
Quoted 11 lines · Ingo Molnar
Quoted 8 lines · Alexander van Heukelum
Quoted 4 lines
My estimation is that if we do it right, your approach will behave better on modern CPUs (which is what matters most for such things), especially on real workloads where there's a considerable instruction-cache pressure. But it should be measured in any case.
Fully agreed. I will do some measurements in the near future, maybe next week. At least noone came up with an absolutely blocking problem with this approach ;).
Quoted 7 lines
how about "it does not build with lguest enabled" as a blocking problem? ;-)
arch/x86/lguest/built-in.o: In function `lguest_init_IRQ':
boot.c:(.init.text+0x33f): undefined reference to `interrupt'config attached.
... other than that it booted fine on a few testboxes here. That's still not an exhaustive test by any means, but it's promising.
Ingo
Quoted 8 lines · Ingo Molnar
Quoted 5 lines · Alexander van Heukelum
Quoted 4 lines
My estimation is that if we do it right, your approach will behave better on modern CPUs (which is what matters most for such things), especially on real workloads where there's a considerable instruction-cache pressure. But it should be measured in any case.
Quoted 6 lines
Quoted 3 lines
Fully agreed. I will do some measurements in the near future, maybe next week. At least noone came up with an absolutely blocking problem with this approach ;).
how about "it does not build with lguest enabled" as a blocking problem? ;-)
Blocking for applying the patch as is, sure... As a proof of concept it is still fine ;).
Quoted 2 lines
arch/x86/lguest/built-in.o: In function `lguest_init_IRQ':
boot.c:(.init.text+0x33f): undefined reference to `interrupt'
It just needs to be fixed. I guess similar problems are to be expected with xen or um.
Thanks,
Alexander
Quoted 3 lines
config attached.
Ingo
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - mmm... Fastmail...
Quoted 12 lines · Ingo Molnar
Quoted 8 lines · Alexander van Heukelum
Quoted 4 lines
My estimation is that if we do it right, your approach will behave better on modern CPUs (which is what matters most for such things), especially on real workloads where there's a considerable instruction-cache pressure. But it should be measured in any case.
Fully agreed. I will do some measurements in the near future, maybe next week. At least noone came up with an absolutely blocking problem with this approach ;).
Quoted 5 lines
how about "it does not build with lguest enabled" as a blocking problem? ;-)
arch/x86/lguest/built-in.o: In function `lguest_init_IRQ':
boot.c:(.init.text+0x33f): undefined reference to `interrupt'
The following makes it compile... Whether it works is a different question ;).
index a5d8e1a..ad7e292 100644
arch/x86/lguest/boot.c +1 -0
@@ -580,6 +580,7 @@ static struct irq_chip lguest_irq_controller = {* interrupt (except 128, which is used for system calls), and then tells the * Linux infrastructure that each interrupt is controlled by our level-based * lguest interrupt controller. */ +void maininterrupt (void );static void __init lguest_init_IRQ (void )
{
unsigned int i;
@@ -590,7 +591,7 @@ static void __init lguest_init_IRQ(void)
* a straightforward 1 to 1 mapping, so force that here.
*/
__get_cpu_var(vector_irq)[vector] = i;
if (vector != SYSCALL_VECTOR) {
- set_intr_gate(vector, interrupt[vector]);
+ set_intr_gate(vector, maininterrupt);
set_irq_chip_and_handler_name(i,
&lguest_irq_controller,
handle_level_irq,
"level");Quoted 3 lines
config attached.
Ingo
Signature · 6 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - One of many happy users: http://www.fastmail.fm/docs/quotes.html
Quoted 2 lines
not taking into account the cost of cs reading (which I don't suspect to be that expensive apart from writting,
GDT accesses have an implied LOCK prefix. Especially on some older CPUs that could be slow.
I don't know if it's a problem or not but it would need some careful benchmarking on different systems to make sure interrupt latencies are not impacted.
Another reason I would be also careful with this patch is that it will likely trigger slow paths in JITs like qemu/vmware/etc.
Also code segment switching is likely not something that current and future micro architectures will spend a lot of time optimizing.
I'm not sure that risk is worth the small improvement in code size.
An alternative BTW to having all the stubs in the executable would be to just dynamically generate them when the interrupt is set up. Then you would only have the stubs around for the interrupts which are actually used.
-Andi
Quoted 9 lines · Andi Kleen
Quoted 2 lines
not taking into account the cost of cs reading (which I don't suspect to be that expensive apart from writting,
GDT accesses have an implied LOCK prefix. Especially on some older CPUs that could be slow.
I don't know if it's a problem or not but it would need some careful benchmarking on different systems to make sure interrupt latencies are not impacted.
That's good to know. I assume this LOCKed bus cycle only occurs if the (hidden) segment information is not cached in some way? How many segments are typically cached? In particular, does it optimize switching between two segments?
Quoted 2 lines
Another reason I would be also careful with this patch is that it will likely trigger slow paths in JITs like qemu/vmware/etc.
Software can be fixed ;).
Quoted 6 lines
Also code segment switching is likely not something that current and future micro architectures will spend a lot of time optimizing.
I'm not sure that risk is worth the small improvement in code size.
I think it is worth exploring a bit more. I feel it should be a neutral change worst-case performance-wise, but I really think the new code is more readable/understandable.
Quoted 4 lines
An alternative BTW to having all the stubs in the executable would be to just dynamically generate them when the interrupt is set up. Then you would only have the stubs around for the interrupts which are actually used.
I was trying to simplify things, not make it even less transparent ;).
Quoted 1 line
-Andi
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - A no graphics, no pop-ups email service
H. Peter Anvin
reviewerQuoted 6 lines · Alexander van Heukelum
That's good to know. I assume this LOCKed bus cycle only occurs if the (hidden) segment information is not cached in some way? How many segments are typically cached? In particular, does it optimize switching between two segments?
Yes, there is a segment descriptor cache (as opposed to the hidden but architectural segment descriptor *registers*, which the Intel documentation confusingly call a "cache".)
It is used to optimize switching between a small number of segments, and was crucial for decent performance on Win9x, which contained a bunch of 16-bit code.
-hpa
Quoted 8 lines · H. Peter Anvin
Quoted 6 lines · Alexander van Heukelum
That's good to know. I assume this LOCKed bus cycle only occurs if the (hidden) segment information is not cached in some way? How many segments are typically cached? In particular, does it optimize switching between two segments?
Quoted 7 lines
Yes, there is a segment descriptor cache (as opposed to the hidden but architectural segment descriptor *registers*, which the Intel documentation confusingly call a "cache".)
It is used to optimize switching between a small number of segments, and was crucial for decent performance on Win9x, which contained a bunch of 16-bit code.
Thanks for the info!
This just means that if there are performance problems, the 'specialized'
handlers should be using the kernel segment or maybe a single common segment. It would still allow us to get rid of the trampolines. A stack trace should be enough to reconstruct which vector was originally called in that case. Only the common_interrupt-codepath needs the original vector as far as I can see.
You just made testing on larger machines with a lot of external interrupts necessary :-/. (Assuming small machines do not show performance problems, that is.)
Greetings,
Alexander
Quoted 1 line
-hpa
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - I mean, what is it about a decent email service?
H. Peter Anvin
reviewerQuoted 11 lines · Alexander van Heukelum
Thanks for the info!
This just means that if there are performance problems, the 'specialized'
handlers should be using the kernel segment or maybe a single common segment. It would still allow us to get rid of the trampolines. A stack trace should be enough to reconstruct which vector was originally called in that case. Only the common_interrupt-codepath needs the original vector as far as I can see.
Quoted 4 lines
You just made testing on larger machines with a lot of external interrupts necessary :-/. (Assuming small machines do not show performance problems, that is.)
Overall, it more than anything else show the x86 architectural braindamage of not having an interrupt vector number register available anywhere. However, I suspect using segment registers is liable to suffer from a "wall of jello" effect once you overflow the segment descriptor cache, which will typically be around 32 entries in size.
Now, at least on my kernel, the existing IRQ stubs are rather weird:
they are padded to 8 bytes and then misaligned onto a 4-byte boundary. Furthermore, at the cost of an extra jump, they can trivially be compressed down to 4 bytes apiece instead of 7-padded-to-8.
-hpa
H. Peter Anvin
reviewerOkay, looking at this some more, the current interrupt stubs are just plain braindead.
We have a large number of push instructions which save a negative number, even when that means using the full 5-byte form; then we use:
unsigned vector = ~regs->orig_ax;
in do_IRQ. This is utterly moronic; if we use the short form push at all times, then we can set the upper bits (which distinguish us from a system call entry) at leisure (via a simple orl in common code), rather than in each stub, which to boot bloats it above the 8-byte mark.
That way, each stub has the simple form:
6A xx E9 yy yy yy yy 90
Down to 8 bytes, including one byte of padding. Already better - we are down to 2K total, and each stub is aligned.
Now, we can do better than that at the cost of an extra branch. The extra branch, however, is a direct unconditional branch and so is not subject to misprediction (good), although it may end up taking an extra icache miss (bad):
we can group our vectors in 8 groups of 32 vectors each. Each contain a stub of the form:
6A xx EB yy
... which jump to a common jump instruction at the end of each group. Thus, each group takes 32*4+5 bytes+3 bytes for alignment = 136 bytes, for a total of 1088 bytes.
This has two disadvantages:
- an extra jump.
- we can no longer redirect a stub away from common code by changing the branch in that slot. We have to instead modify the IDT. This means "dedicated" interrupts don't get the vector number at all, which is probably fine -- to be honest, I'm not sure if they do at the moment either.
Fixing the first of these I think is a no-brainer. That will cut the size of the existing stub pool by almost half. The second is more of a judgement call, and I'd like to see performance numbers for it. Either which way, I think it's worthwhile to consider this as an alternative to
playing segmentation tricks, which I think could have really nasty
side effects.
-hpa
Quoted 6 lines · H. Peter Anvin
- we can no longer redirect a stub away from common code by changing the branch in that slot. We have to instead modify the IDT. This means "dedicated" interrupts don't get the vector number at all, which is probably fine -- to be honest, I'm not sure if they do at the moment either.
They do, and the various patches to multiplex things like IPIs across multiple vectors rely on it.
J
Quoted 6 lines
Fixing the first of these I think is a no-brainer. That will cut the size of the existing stub pool by almost half. The second is more of a judgement call, and I'd like to see performance numbers for it. Either which way, I think it's worthwhile to consider this as an alternative to
playing segmentation tricks, which I think could have really nasty
side effects.
Or again just generate them on demand when the interrupt is set up. If you really have 240 interrupts sources you can afford the 5k likely, but for most there will be only a minimum number of stubs.
Although frankly I suspect there are far easier ways to save 5k of memory.
-Andi
H. Peter Anvin
reviewerQuoted 7 lines · Andi Kleen
Or again just generate them on demand when the interrupt is set up. If you really have 240 interrupts sources you can afford the 5k likely, but for most there will be only a minimum number of stubs.
Although frankly I suspect there are far easier ways to save 5k of memory.
Generating them dynamically is probably pretty ugly too, though.
Shrinking the whole table down to 2K by just regularizing the structure is trivial, though, and should almost certainly be a win. The more esoteric ideas are probably worse.
-hpa
Quoted 10 lines · H. Peter Anvin
Quoted 7 lines · Andi Kleen
Or again just generate them on demand when the interrupt is set up. If you really have 240 interrupts sources you can afford the 5k likely, but for most there will be only a minimum number of stubs.
Although frankly I suspect there are far easier ways to save 5k of memory.
Generating them dynamically is probably pretty ugly too, though.
Why? The only slightly tricky thing is that they need to be in no NX space. Then it's just a few bytes patched in a template.
Quoted 3 lines
Shrinking the whole table down to 2K by just regularizing the structure is trivial, though, and should almost certainly be a win. The more esoteric ideas are probably worse.
Just think how much memory you could safe elsewhere with the same effort.
-Andi
Quoted 11 lines · Alexander van Heukelum
Quoted 9 lines · Andi Kleen
Quoted 2 lines
not taking into account the cost of cs reading (which I don't suspect to be that expensive apart from writting,
GDT accesses have an implied LOCK prefix. Especially on some older CPUs that could be slow.
I don't know if it's a problem or not but it would need some careful benchmarking on different systems to make sure interrupt latencies are not impacted.
That's not a real issue on anything produced in this decade as we have had per CPU GDTs in Linux for about a decade as well.
It's only an issue on ancient CPUs that export all their LOCKed cycles to the bus. Pentium and older or so. The PPro got it right already.
What matters is what i said before: the actual raw cycle count before and after the patch, on the two main classes of CPUs, and the amount of icache we can save.
Quoted 9 lines
That's good to know. I assume this LOCKed bus cycle only occurs if the (hidden) segment information is not cached in some way? How many segments are typically cached? In particular, does it optimize switching between two segments?
Quoted 2 lines
Another reason I would be also careful with this patch is that it will likely trigger slow paths in JITs like qemu/vmware/etc.
Software can be fixed ;).
Yes, and things like vmware were never a reason to hinder Linux.
Quoted 10 lines
Quoted 6 lines
Also code segment switching is likely not something that current and future micro architectures will spend a lot of time optimizing.
I'm not sure that risk is worth the small improvement in code size.
I think it is worth exploring a bit more. I feel it should be a neutral change worst-case performance-wise, but I really think the new code is more readable/understandable.
It's all measurable, so the vague "risk" mentioned above can be dispelled via hard numbers.
Quoted 7 lines
Quoted 4 lines
An alternative BTW to having all the stubs in the executable would be to just dynamically generate them when the interrupt is set up. Then you would only have the stubs around for the interrupts which are actually used.
I was trying to simplify things, not make it even less transparent ;).
yep, the complexity of dynamic stubs is the last thing we need here.
And as hpa's comments point it out, compressing the rather stupid irq stubs might be a third option that looks promising as well.
Ingo
Quoted 15 lines · Ingo Molnar
Quoted 11 lines · Alexander van Heukelum
Quoted 9 lines · Andi Kleen
Quoted 2 lines
not taking into account the cost of cs reading (which I don't suspect to be that expensive apart from writting,
GDT accesses have an implied LOCK prefix. Especially on some older CPUs that could be slow.
I don't know if it's a problem or not but it would need some careful benchmarking on different systems to make sure interrupt latencies are not impacted.
Quoted 5 lines
That's not a real issue on anything produced in this decade as we have had per CPU GDTs in Linux for about a decade as well.
It's only an issue on ancient CPUs that export all their LOCKed cycles to the bus. Pentium and older or so. The PPro got it right already.
??? LOCK slowness is not because of the bus. And I know you know that Ingo, so I don't know why you wrote that bogosity above.
Quoted 2 lines
What matters is what i said before: the actual raw cycle count before and after the patch, on the two main classes of CPUs, and the amount
iirc there are at least between three and five classes of CPUs that matter (P6, K8, P4 and possibly Atom and C3). But I would only expect P4 to be a real problem.
Quoted 11 lines
Quoted 9 lines
That's good to know. I assume this LOCKed bus cycle only occurs if the (hidden) segment information is not cached in some way? How many segments are typically cached? In particular, does it optimize switching between two segments?
Quoted 2 lines
Another reason I would be also careful with this patch is that it will likely trigger slow paths in JITs like qemu/vmware/etc.
Software can be fixed ;).
Yes, and things like vmware were never a reason to hinder Linux.
Hopefully the users agree with you on that.
But anyways having to fix the JIT for saving 3-5k of memory would seem like a bad payoff in terms of effort:gain. Yes I know you personally wouldn't need to fix them, but wasting other engineer's time is nearly as bad as your own.
Quoted 7 lines
Quoted 7 lines
Quoted 4 lines
An alternative BTW to having all the stubs in the executable would be to just dynamically generate them when the interrupt is set up. Then you would only have the stubs around for the interrupts which are actually used.
I was trying to simplify things, not make it even less transparent ;).
Doesn't make sense to me. The current code is not complex at all, just not particularly efficient. Yours might be better (at some risk), but simpler is probably not the right word to describe it.
Quoted 2 lines
yep, the complexity of dynamic stubs is the last thing we need here.
I don't think it's particularly complex. You just have a few bytes and you fill in the number and the target.
-Andi
Quoted 2 lines · Andi Kleen
??? LOCK slowness is not because of the bus. And I know you know that Ingo, so I don't know why you wrote that bogosity above.
Why are the accesses locked? Is it because it does an update of the accessed bit in the descriptor? (We should be pre-setting them all anyway.)
J
H. Peter Anvin
reviewerQuoted 9 lines · Jeremy Fitzhardinge
Quoted 3 lines · Andi Kleen
??? LOCK slowness is not because of the bus. And I know you know that Ingo, so I don't know why you wrote that bogosity above.
Why are the accesses locked? Is it because it does an update of the accessed bit in the descriptor? (We should be pre-setting them all anyway.)
It is, but the locked access is unconditional. Similar to any other read/modify/write transaction -- the write is required to release the lock.
-hpa
Quoted 3 lines · Jeremy Fitzhardinge
Why are the accesses locked? Is it because it does an update of the accessed bit in the descriptor? (We should be pre-setting them all anyway.)
yes, the accessed bit in the segment descriptor has to be updated in an atomic transaction: the CPU has to do a MESI coherent read+compare+write transaction, without damaging other updates to the 6 bytes segment descriptor.
Old OSs implemented paging to disk by swapping out segments based on the accessed bit, and clearing the present and accessed bit when the segment is swapped out.
But given that all our GDT entries have the accessed bit set on Linux, there's no physical reason why the CPU should be using a locked cycle here - only to stay compatible with ancient stuff.
So ... that notion just survived in the backwards-compatibility stream of CPU enhancements, over the past 10 years.
On 64-bit Linux there's no reason to maintain that principle, so i'd expect future CPUs to relax this even more, were it ever to show up on the performance radar. Note that SYSCALL/SYSRET already optimize that away.
Ingo
H. Peter Anvin
reviewerQuoted 3 lines · Ingo Molnar
yes, the accessed bit in the segment descriptor has to be updated in an atomic transaction: the CPU has to do a MESI coherent read+compare+write transaction, without damaging other updates to the 6 bytes segment descriptor.
8 bytes, rather.
Quoted 8 lines · H. Peter Anvin
Quoted 5 lines · Ingo Molnar
yes, the accessed bit in the segment descriptor has to be updated in an atomic transaction: the CPU has to do a MESI coherent read+compare+write transaction, without damaging other updates to the 6 bytes segment descriptor.
8 bytes, rather.
heh, yes of course :-)
Ingo
Quoted 19 lines · Andi Kleen
Quoted 18 lines · Ingo Molnar
Quoted 11 lines · Alexander van Heukelum
Quoted 9 lines · Andi Kleen
Quoted 2 lines
not taking into account the cost of cs reading (which I don't suspect to be that expensive apart from writting,
GDT accesses have an implied LOCK prefix. Especially on some older CPUs that could be slow.
I don't know if it's a problem or not but it would need some careful benchmarking on different systems to make sure interrupt latencies are not impacted.
That's not a real issue on anything produced in this decade as we have had per CPU GDTs in Linux for about a decade as well.
Quoted 6 lines
Quoted 3 lines
It's only an issue on ancient CPUs that export all their LOCKed cycles to the bus. Pentium and older or so. The PPro got it right already.
??? LOCK slowness is not because of the bus. And I know you know that Ingo, so I don't know why you wrote that bogosity above.
.. of course the historic LOCK slowness was all due to the system bus:
very old CPUs exported a LOCK signal to the system bus for every LOCK-prefix access (implicit and explicit) and that made it _really_ expensive. (hundreds of cycles)
... on reasonably modern CPUs the LOCK-ed access has been abstracted away to within the CPU, and the cost of LOCK-ed access is rather low (think 10-20 cycles - of course only if there's no cache miss cost) (That's obviously the case with the GDT, with is both per CPU and well cached.)
on _really_ modern CPUs LOCK can be as cheap as just a few cycles - so low that we can stop bothering about it in the future. There's no fundamental physical reason why the LOCK prefix (implicit or explicit) should be expensive.
the real reason why Alexander's patch needs to be measured is not the LOCK cycle of GDT accesses but what i pointed out in my first mail:
the segmentation trick it plays. And that's why shrinking the stubs is probably a better idea which should be tried first.
... anyway, the unacceptable tone of your reply shows that you still have not changed a bit in your old habit of attacking and bullying people on lkml. All the other Intel engineers i'm working with as a maintainer show a very professional approach and are very easy to work with. You need to stop your attacks, and until you change this negative way of working with people i'll continue to ignore you.
Ingo
Sorry to reply so late on this slightly offtopic rant...
Quoted 15 lines · Ingo Molnar
Quoted 8 lines · Andi Kleen
Quoted 3 lines · Ingo Molnar
It's only an issue on ancient CPUs that export all their LOCKed cycles to the bus. Pentium and older or so. The PPro got it right already.
??? LOCK slowness is not because of the bus. And I know you know that Ingo, so I don't know why you wrote that bogosity above.
.. of course the historic LOCK slowness was all due to the system bus:
very old CPUs exported a LOCK signal to the system bus for every LOCK-prefix access (implicit and explicit) and that made it _really_ expensive. (hundreds of cycles)
Quoted 5 lines
... on reasonably modern CPUs the LOCK-ed access has been abstracted away to within the CPU, and the cost of LOCK-ed access is rather low (think 10-20 cycles - of course only if there's no cache miss cost) (That's obviously the case with the GDT, with is both per CPU and well cached.)
Locked instruction AFAIR is about 50 cycles on Core2. I think it is a bit lower on K8. On Nehalem, which has optimisations for these, I have heard it is still about 20-25 cycles. Although I don't have one, so I don't actually know.
These (on my Core2) don't seem to pipeline at all with other instructions either. So on my Core2, a locked instruction is worth maybe 150-200 regular pipelined, superscalar instructions.
There is another big reason why lock instructions are expensive, and that is because they have to prevent subsequent loads from passing any previous stores becoming visible. This in theory could be somewhat speculated, but no matter what happens, the program visible state can't be committed until the stores are.
I heard from an Intel hardware engineer that Nehalem has some really fancy logic in it to make locked instructions "free", that was nacked from earlier CPUs because it was too costly. So obviously it is taking a fair whack of transistors or power for them to do it. And even then it is far from free, but still seems to be one or two orders of magnitude more expensive than a regular instruction.
Quoted 1 line
on _really_ modern CPUs LOCK can be as cheap as just a few cycles - so
Oh, maybe I'm mistaken about Nehalem then? How many is "just a few"? If it is 25 non-pipelined cycles, then that's still 100 instructions if it is a 4 issue machine.
Quoted 3 lines
low that we can stop bothering about it in the future. There's no fundamental physical reason why the LOCK prefix (implicit or explicit) should be expensive.
Even if they could make it free on the software side, it is obviously expensive on the hardware side. Not bothering about it is a copout. The atomic instruction speedups in Nehalem are cool, but what would have been even cooler is if Intel had decided *not* to spend resources making this cheaper because they found Linux has so few locked instructions :)
Even if somehow the x86 ISA didn't have the implicit memory ordering requirement in the lock instruction, I think it's obviously a special case path that doesn't fit in with a load/store uarch (whether they implement it in uops with ll/sc like thing or whatnot, it's going to need special logic).
IMO, we shouldn't stop bothering about LOCK prefix in the forseeable future.
H. Peter Anvin
reviewerQuoted 8 lines · Nick Piggin
I heard from an Intel hardware engineer that Nehalem has some really fancy logic in it to make locked instructions "free", that was nacked from earlier CPUs because it was too costly. So obviously it is taking a fair whack of transistors or power for them to do it. And even then it is far from free, but still seems to be one or two orders of magnitude more expensive than a regular instruction.
Last I heard it was still a dozen-ish cycles even on Nehalem.
Quoted 4 lines
IMO, we shouldn't stop bothering about LOCK prefix in the forseeable future.
Even if a CPU came out *today* that had zero-cost locks we'd have to worry about it for at least another 5-10 years. The good news is that we're doing pretty good with it for now, but I don't believe in general we can avoid the fact that improving LOCK performance helps everything when you're dealing with large numbers of cores/threads.
-hpa
Quoted 9 lines · H. Peter Anvin
Quoted 6 lines · Nick Piggin
I heard from an Intel hardware engineer that Nehalem has some really fancy logic in it to make locked instructions "free", that was nacked from earlier CPUs because it was too costly. So obviously it is taking a fair whack of transistors or power for them to do it. And even then it is far from free, but still seems to be one or two orders of magnitude more expensive than a regular instruction.
Last I heard it was still a dozen-ish cycles even on Nehalem.
Right -- that's their definition of "free", and even comes after they seem to have put a large amount of effort into it. So they are still expensive.
Quoted 8 lines
Quoted 2 lines
IMO, we shouldn't stop bothering about LOCK prefix in the forseeable future.
Even if a CPU came out *today* that had zero-cost locks we'd have to worry about it for at least another 5-10 years. The good news is that we're doing pretty good with it for now, but I don't believe in general we can avoid the fact that improving LOCK performance helps everything when you're dealing with large numbers of cores/threads.
There is a balance, though. And that is going to depend on what other low hanging fruit the CPU has eaten, and what the ratio of lock instructions is on the target workload. So it's always preferable to reduce their number. (by definition they will always be more difficult for the CPU to execute)
Quoted 2 lines · Ingo Molnar
And as hpa's comments point it out, compressing the rather stupid irq stubs might be a third option that looks promising as well.
... and we should try and see how far we can compress those stubs, before we do any segment register based tricks.
Ingo
H. Peter Anvin
reviewerQuoted 8 lines · Ingo Molnar
Quoted 2 lines · Ingo Molnar
And as hpa's comments point it out, compressing the rather stupid irq stubs might be a third option that looks promising as well.
... and we should try and see how far we can compress those stubs, before we do any segment register based tricks.
Using the techniques previously mentioned, for 224 vectors:
1792 bytes ( 8 bytes/stub) - trivial.
1568 bytes ( 7 bytes/stub) - same without alignment.
952 bytes (~4 bytes/stub) - extra jump needed.
For comparison, the IDT itself is 2048 bytes on x86-32 and 4096 bytes on x86-64.
-hpa
Quoted 10 lines · H. Peter Anvin
Quoted 8 lines · Ingo Molnar
Quoted 2 lines · Ingo Molnar
And as hpa's comments point it out, compressing the rather stupid irq stubs might be a third option that looks promising as well.
... and we should try and see how far we can compress those stubs, before we do any segment register based tricks.
Quoted 8 lines
Using the techniques previously mentioned, for 224 vectors:
1792 bytes ( 8 bytes/stub) - trivial.
1568 bytes ( 7 bytes/stub) - same without alignment.
952 bytes (~4 bytes/stub) - extra jump needed.For comparison, the IDT itself is 2048 bytes on x86-32 and 4096 bytes on x86-64.
sounds like a plan :)
Ingo
[Ingo Molnar - Tue, Nov 04, 2008 at 10:52:45PM +0100]
| | * H. Peter Anvin <[email protected]> wrote: | | > Ingo Molnar wrote: | > > * Ingo Molnar <[email protected]> wrote: | > > | > >> And as hpa's comments point it out, compressing the rather stupid | > >> irq stubs might be a third option that looks promising as well. | > > | > > ... and we should try and see how far we can compress those stubs, | > > before we do any segment register based tricks. | > > | > | > Using the techniques previously mentioned, for 224 vectors: | > | > 1792 bytes ( 8 bytes/stub) - trivial. | > 1568 bytes ( 7 bytes/stub) - same without alignment. | > 952 bytes (~4 bytes/stub) - extra jump needed. | > | > For comparison, the IDT itself is 2048 bytes on x86-32 and 4096 bytes on | > x86-64. | | sounds like a plan :) | | Ingo |
Ingo, what the conclusion is? As I understand from the thread --
1) Implement Peter's proposed cleanup/compress.
2) Test Alexander's patche.
Did I miss something?
- Cyrill -
H. Peter Anvin
reviewerQuoted 8 lines · Cyrill Gorcunov
Ingo, what the conclusion is? As I understand from the thread --
1) Implement Peter's proposed cleanup/compress.
2) Test Alexander's patche.Did I miss something?
Nope, that's pretty much it.
However, there are good reason to believe that using this kind of segment selector tricks is probably a bad idea in the long term, especially since CPU vendors have strong incentives to reduce the size of the segment descriptor cache now when none of the mainstream OSes rely on more than a small handful of segments.
I was planning to look at doing the obvious stub shrink today.
-hpa
[H. Peter Anvin - Wed, Nov 05, 2008 at 10:04:50AM -0800]
| Cyrill Gorcunov wrote: | > | > Ingo, what the conclusion is? As I understand from the thread -- | > | > 1) Implement Peter's proposed cleanup/compress. | > 2) Test Alexander's patche. | > | > Did I miss something? | > | | Nope, that's pretty much it. | | However, there are good reason to believe that using this kind of | segment selector tricks is probably a bad idea in the long term, | especially since CPU vendors have strong incentives to reduce the size | of the segment descriptor cache now when none of the mainstream OSes | rely on more than a small handful of segments. | | I was planning to look at doing the obvious stub shrink today. | | -hpa |
I see. Thanks! Btw Peter, I remember I read long time ago about segment caches (well... in time of DOS programming actually). But there was only 'common' words like this cache exist. But maybe it's possible to know what exactly size of such a cache is? You mentoined number 32. (heh... I hadn't remember it until you mentoined about such a cache :-)
- Cyrill -
H. Peter Anvin
reviewerQuoted 8 lines · Cyrill Gorcunov
I see. Thanks! Btw Peter, I remember I read long time ago about segment caches (well... in time of DOS programming actually). But there was only 'common' words like this cache exist. But maybe it's possible to know what exactly size of such a cache is? You mentoined number 32. (heh... I hadn't remember it until you mentoined about such a cache :-)
As with any other caching structure, you can discover its size, associativity, and replacement policy by artificially trying to provoke patterns that produce pathological timings.
At Transmeta, at one time we used a 32-entry direct-mapped cache, which ended up with a ~96% hit rate on common Win95 benchmarks.
I should, however, make it clear that there are other alternatives for speeding up segment descriptor loading, and not all of them rely on a cache.
-hpa
[H. Peter Anvin - Wed, Nov 05, 2008 at 10:20:23AM -0800]
| Cyrill Gorcunov wrote: | > | > I see. Thanks! Btw Peter, I remember I read long time ago about | > segment caches (well... in time of DOS programming actually). But | > there was only 'common' words like this cache exist. But maybe | > it's possible to know what exactly size of such a cache is? | > You mentoined number 32. (heh... I hadn't remember it until | > you mentoined about such a cache :-) | > | | As with any other caching structure, you can discover its size, | associativity, and replacement policy by artificially trying to provoke | patterns that produce pathological timings. | | At Transmeta, at one time we used a 32-entry direct-mapped cache, which | ended up with a ~96% hit rate on common Win95 benchmarks. | | I should, however, make it clear that there are other alternatives for | speeding up segment descriptor loading, and not all of them rely on a cache. | | -hpa |
Thanks a lot for explanation!
- Cyrill -
A message that is not in the archive (sent off-list or not yet received): [email protected]
H. Peter Anvin
reviewerQuoted 8 lines · Alexander van Heukelum
In general: after applying the patch, latencies are more often seen by the rdtsctest. It also seems to cause a small percentage decrease in speed of hackbench. Looking at the latency histograms I believe this is a real effect, but I could not do enough boots/runs to make this a certainty from the runtimes alone.
Quoted 7 lines
At least for this PC, doing hpa's suggested cleanup of the stub table is the right way to go for now... A second option would be to get rid of the stub table by assigning each important vector a unique handler and to make sure those handlers do not rely on the vector number at all.
Hi Alexander,
First of all, great job on the timing analysis. I believe this confirms the concerns that I had about this technique.
Here is a prototype patch of the compressed IRQ stubs -- this patch compresses them down to 7 stubs per 32-byte cache line (or part of cache line) at the expense of a back-to-back jmp which has the potential of being ugly on some pipelines (we can only get 4 stubs into 32 bytes without that).
Would you be willing to run your timing test on this patch? This isn't submission-quality since it commingles multiple changes, and it needs some cleanup, but it should be useful for testing.
As a side benefit it eliminates some gratuitous differences between the 32- and 64-bit code.
-hpa
arch/x86/include/asm/hw_irq.h +1 -3
@@ -109,9 +109,7 @@ extern asmlinkage void smp_invalidate_interrupt(struct pt_regs *);#endif #endif -#ifdef CONFIG_X86_32 -extern void (*const interrupt[NR_VECTORS ])(void ); -#endif +extern void (*__initconst interrupt[NR_VECTORS -FIRST_EXTERNAL_VECTOR ])(void );typedef int vector_irq_t [NR_VECTORS ];DECLARE_PER_CPU (vector_irq_t, vector_irq);
arch/x86/kernel/entry_32.S +24 -14
@@ -619,29 +619,38 @@ END(syscall_badsys) 27:; /* - * Build the entry stubs and pointer table with - * some assembler magic. + * Build the entry stubs and pointer table with some assembler magic. + * We pack 7 stubs into a single 32-byte chunk, which will fit in a + * single cache line on all modern x86 implementations. */ -.section .rodata,"a" + .section ".init.rodata","a" ENTRY(interrupt) -.text - + .text + .balign 32 ENTRY(irq_entries_start) RING0_INT_FRAME -vector=0 -.rept NR_VECTORS - ALIGN - .if vector +vector=FIRST_EXTERNAL_VECTOR +.rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7 + .balign 32 + .rept 7 + .if vector < NR_VECTORS + .if vector != FIRST_EXTERNAL_VECTOR CFI_ADJUST_CFA_OFFSET -4 - .endif -1: pushl $~(vector) + .endif +1: pushl $(~vector+0x80) /* Note: always in signed byte range */ CFI_ADJUST_CFA_OFFSET 4 - jmp common_interrupt - .previous + .if ((vector-FIRST_EXTERNAL_VECTOR)%7) != 6 + jmp 2f + .endif + .previous .long 1b - .text + .text vector=vector+1 + .endif + .endr +2: jmp common_interrupt .endr + .balign 32 END(irq_entries_start) .previous
@@ -654,6 +663,7 @@ END(interrupt) */ ALIGN common_interrupt: + addl $-0x80,(%esp) /* Adjust vector into the [-256,-1] range */ SAVE_ALL TRACE_IRQS_OFF movl %esp,%eax
arch/x86/kernel/entry_64.S +44 -3
68 lines not on this page · raw message
arch/x86/kernel/irqinit_32.c +1 -1
@@ -129,7 +129,7 @@ void __init native_init_IRQ(void)for (i =FIRST_EXTERNAL_VECTOR ; i <NR_VECTORS ; i++) {/* SYSCALL_VECTOR was reserved in trap_init. */ if (i !=SYSCALL_VECTOR ) -set_intr_gate (i, interrupt[i]); +set_intr_gate (i, interrupt[i-FIRST_EXTERNAL_VECTOR ]); }
arch/x86/kernel/irqinit_64.c +0 -66
78 lines not on this page · raw message
arch/x86/lguest/boot.c +2 -1
@@ -590,7 +590,8 @@ static void __init lguest_init_IRQ(void)* a straightforward 1 to 1 mapping, so force that here. */ __get_cpu_var (vector_irq)[vector] = i;if (vector !=SYSCALL_VECTOR ) { -set_intr_gate (vector, interrupt[vector]); +set_intr_gate (vector, + interrupt[vector-FIRST_EXTERNAL_VECTOR ]);set_irq_chip_and_handler_name (i, &lguest_irq_controller, handle_level_irq,"level" );
Quoted 7 lines
Here is a prototype patch of the compressed IRQ stubs -- this patch compresses them down to 7 stubs per 32-byte cache line (or part of cache line) at the expense of a back-to-back jmp which has the potential of being ugly on some pipelines (we can only get 4 stubs into 32 bytes without that).
You could actually get 4-byte stubs, using a 16-bit call (66 e8 ww ww). But it would be slower, since we won't be pairing it with a ret.
I suspect we could get it down to three bytes, by sharing the last byte of the four-byte call sequence with the first byte of the next:
66 e8 ff 66 e8 fc 66 e8 f9 66 e8 f6 ...
Every three bytes a new stub begins; it's a four-byte call to offset 0x6703 relative to the beginning of the first stub.
Can anyone better 24 bits/stub?
Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain.
Quoted 10 lines · Avi Kivity
Quoted 7 lines
Here is a prototype patch of the compressed IRQ stubs -- this patch compresses them down to 7 stubs per 32-byte cache line (or part of cache line) at the expense of a back-to-back jmp which has the potential of being ugly on some pipelines (we can only get 4 stubs into 32 bytes without that).
You could actually get 4-byte stubs, using a 16-bit call (66 e8 ww ww). But it would be slower, since we won't be pairing it with a ret.
Quoted 7 lines
I suspect we could get it down to three bytes, by sharing the last byte of the four-byte call sequence with the first byte of the next:
66 e8 ff 66 e8 fc 66 e8 f9 66 e8 f6 ...
Every three bytes a new stub begins; it's a four-byte call to offset
0x6703relative to the beginning of the first stub.Can anyone better 24 bits/stub?
I actually got it down to 16 bits: use a 16-bit code segment, so you can drop the address size override:
e8 ff e8 fd e8 fb ...
of course the common code has to jump back to a 32-bit code segment.
Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain.
H. Peter Anvin
reviewerQuoted 9 lines · Avi Kivity
Quoted 6 lines
Here is a prototype patch of the compressed IRQ stubs -- this patch compresses them down to 7 stubs per 32-byte cache line (or part of cache line) at the expense of a back-to-back jmp which has the potential of being ugly on some pipelines (we can only get 4 stubs into 32 bytes without that).
You could actually get 4-byte stubs, using a 16-bit call (66 e8 ww ww). But it would be slower, since we won't be pairing it with a ret.
Yes, I would consider that a theoretical exercise only :)
Quoted 7 lines
I suspect we could get it down to three bytes, by sharing the last byte of the four-byte call sequence with the first byte of the next:
66 e8 ff 66 e8 fc 66 e8 f9 66 e8 f6 ...
Every three bytes a new stub begins; it's a four-byte call to offset
0x6703relative to the beginning of the first stub.Can anyone better 24 bits/stub?
On the entirely silly level...
CC xx
-hpa
Quoted 5 lines · H. Peter Anvin
Quoted 5 lines
I suspect we could get it down to three bytes, by sharing the last byte of the four-byte call sequence with the first byte of the next:
66 e8 ff 66 e8 fc 66 e8 f9 66 e8 f6 ...
Quoted 7 lines
Quoted 3 lines
Every three bytes a new stub begins; it's a four-byte call to offset
0x6703relative to the beginning of the first stub.Can anyone better 24 bits/stub?
On the entirely silly level...
CC xx
Nice. Can actually go to zero, by pointing the IDT at (unmapped_area + vector), and deducing the vector in the page fault handler from cr2.
Signature · 1 line
error compiling committee.c: too many arguments to function
Quoted 10 lines · Avi Kivity
Quoted 9 lines · H. Peter Anvin
Quoted 9 lines
I suspect we could get it down to three bytes, by sharing the last byte of the four-byte call sequence with the first byte of the next:
66 e8 ff 66 e8 fc 66 e8 f9 66 e8 f6 ...
Every three bytes a new stub begins; it's a four-byte call to offset
0x6703relative to the beginning of the first stub.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
Can anyone better 24 bits/stub?
On the entirely silly level...
CC xx
Nice. Can actually go to zero, by pointing the IDT at (
unmapped_area+ vector), and deducing the vector in the page fault handler from cr2.
That would be still one byte, otherwise you wouldn't get a unique index.
-Andi
Signature · 1 line
[email protected]
Quoted 5 lines · Andi Kleen
Quoted 2 lines
Nice. Can actually go to zero, by pointing the IDT at (
unmapped_area+ vector), and deducing the vector in the page fault handler from cr2.That would be still one byte, otherwise you wouldn't get a unique index.
One virtual byte; zero physical bytes. unmapped_area above need not be mapped.
Signature · 1 line
error compiling committee.c: too many arguments to function
Quoted 10 lines · Avi Kivity
Quoted 9 lines · H. Peter Anvin
Quoted 9 lines
I suspect we could get it down to three bytes, by sharing the last byte of the four-byte call sequence with the first byte of the next:
66 e8 ff 66 e8 fc 66 e8 f9 66 e8 f6 ...
Every three bytes a new stub begins; it's a four-byte call to offset
0x6703relative to the beginning of the first stub.
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
Can anyone better 24 bits/stub?
On the entirely silly level...
CC xx
Nice. Can actually go to zero, by pointing the IDT at (
unmapped_area+ vector), and deducing the vector in the page fault handler from cr2.
Hi all,
We started the discussion with doing away with the whole jump array entirely, by changing the value of the CS index in the IDT. This needs the GDT to be extended with 256 entries, but an entire page (space for 512 entries) was already reserved anyhow! I think there is still some problem with the patch I sent due to some code depending on certain values of the CS index, but the system I've benchmarked on seemed to behave.
I did a set of benchmarks on an 8-way Xeon in 64-bit mode. The system was loaded with an instance of bonnie++ pinned to processor 0, and all 8 processors were running a program doing (almost) adjacent rdtsc's. Bonnie++ causes interrupts and the latencies due to these show up as larger time intervals. Complete runs of bonnie++ in fast mode were sampled this way for a current -rc6 kernel and an -rc6 kernel plus my patch. The total sampling time was 30 minutes for each run. Per kernel I did one run as a warm-up and another two runs to measure the latencies. The results for measured latencies between 5 and 1000 microseconds are shown in the attached graph. Above 1000 microseconds there is only one big
contribution: at 40000 microseconds ;). The surface below the graph is a measure of time.
Observations (for this test load!):
Near 200, 250 and 350 microseconds, the peaks shift to longer latencies for the cs-changing code by about 10 microseconds, but the total time spent is pretty much constant.
The highest latencies for the cs-changing code are near 600 and 650 microseconds. The highest latencies for the current code are near 800 and 850 microseconds.
The total surface of the graphs between 5 and 1000 microseconds is within an error estimate of 1% equal for both cases, and is about 0.69% of the total time.
Most time is spent measuring 'latencies' of less than 5 micro- seconds, since bonnie++ is taking only about 5% cpu time on a single cpu most of the time, and only up to 50% on a single cpu during a short time in the file creation benchmark.
Greetings,
Alexander
Quoted 54 lines · Alexander van Heukelum
Quoted 10 lines · Avi Kivity
Quoted 9 lines · H. Peter Anvin
Quoted 9 lines
I suspect we could get it down to three bytes, by sharing the last byte of the four-byte call sequence with the first byte of the next:
66 e8 ff 66 e8 fc 66 e8 f9 66 e8 f6 ...
Every three bytes a new stub begins; it's a four-byte call to offset
0x6703relative to the beginning of the first stub.Quoted 8 lines
Quoted 5 lines
Quoted 1 line
Can anyone better 24 bits/stub?
On the entirely silly level...
CC xx
Nice. Can actually go to zero, by pointing the IDT at (
unmapped_area+ vector), and deducing the vector in the page fault handler from cr2.Hi all,
We started the discussion with doing away with the whole jump array entirely, by changing the value of the CS index in the IDT. This needs the GDT to be extended with 256 entries, but an entire page (space for 512 entries) was already reserved anyhow! I think there is still some problem with the patch I sent due to some code depending on certain values of the CS index, but the system I've benchmarked on seemed to behave.
I did a set of benchmarks on an 8-way Xeon in 64-bit mode. The system was loaded with an instance of bonnie++ pinned to processor 0, and all 8 processors were running a program doing (almost) adjacent rdtsc's. Bonnie++ causes interrupts and the latencies due to these show up as larger time intervals. Complete runs of bonnie++ in fast mode were sampled this way for a current -rc6 kernel and an -rc6 kernel plus my patch. The total sampling time was 30 minutes for each run. Per kernel I did one run as a warm-up and another two runs to measure the latencies. The results for measured latencies between 5 and 1000 microseconds are shown in the attached graph. Above 1000 microseconds there is only one big
contribution: at 40000 microseconds ;). The surface below the graph is a measure of time.Observations (for this test load!):
Near 200, 250 and 350 microseconds, the peaks shift to longer latencies for the cs-changing code by about 10 microseconds, but the total time spent is pretty much constant.
The highest latencies for the cs-changing code are near 600 and 650 microseconds. The highest latencies for the current code are near 800 and 850 microseconds.
Quoted 8 lines
The total surface of the graphs between 5 and 1000 microseconds is within an error estimate of 1% equal for both cases, and is about 0.69% of the total time.
Most time is spent measuring 'latencies' of less than 5 micro- seconds, since bonnie++ is taking only about 5% cpu time on a single cpu most of the time, and only up to 50% on a single cpu during a short time in the file creation benchmark.
I now did the benchmarks for the same -rc6 with hpa's 4-byte stubs too. Same machine. It's significantly better than the other two options in terms of speed. It takes about 7% less cpu to handle the interrupts. (0.64% cpu instead of 0.69%.) I have to run now, I'll let interpreting the histogram to someone else ;).
Greetings,
Alexander
Quoted 6 lines · Alexander van Heukelum
I now did the benchmarks for the same -rc6 with hpa's 4-byte stubs too. Same machine. It's significantly better than the other two options in terms of speed. It takes about 7% less cpu to handle the interrupts. (0.64% cpu instead of 0.69%.) I have to run now, I'll let interpreting the histogram to someone else ;).
This is noise. 0.05% cpu on a 1GHz machine servicing 1000 interrupt/sec boils down to 500 cycles/interrupt. These changes shouldn't amount to so much (and I doubt you have 1000 interrupts/sec with a single disk)..
I'm sorry, but the whole effort is misguided, in my opinion. If you want to optimize, try reducing the number of interrupts that occur rather than saving a few cycles in the interrupt path.
Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain.
Quoted 8 lines · Avi Kivity
Quoted 6 lines · Alexander van Heukelum
I now did the benchmarks for the same -rc6 with hpa's 4-byte stubs too. Same machine. It's significantly better than the other two options in terms of speed. It takes about 7% less cpu to handle the interrupts. (0.64% cpu instead of 0.69%.) I have to run now, I'll let interpreting the histogram to someone else ;).
Quoted 7 lines
This is noise. 0.05% cpu on a 1GHz machine servicing 1000 interrupt/sec boils down to 500 cycles/interrupt. These changes shouldn't amount to so much (and I doubt you have 1000 interrupts/sec with a single disk)..
I'm sorry, but the whole effort is misguided, in my opinion. If you want to optimize, try reducing the number of interrupts that occur rather than saving a few cycles in the interrupt path.
the goal was not to optimize those workloads - the goal was to (try to) validate those irq trampoline changes / cleanups. We went with hpa's changes in the end which compresses the trampolines - that reduces the $icache footprint which is hard to measure but a very real concern on real workloads.
Ingo
Quoted 10 lines · On Sunday 30 November 2008 04:52:41 Avi Kivity wrote:
Quoted 5 lines · Alexander van Heukelum
I now did the benchmarks for the same -rc6 with hpa's 4-byte stubs too. Same machine. It's significantly better than the other two options in terms of speed. It takes about 7% less cpu to handle the interrupts. (0.64% cpu instead of 0.69%.) I have to run now, I'll let interpreting the histogram to someone else ;).
This is noise. 0.05% cpu on a 1GHz machine servicing 1000 interrupt/sec boils down to 500 cycles/interrupt. These changes shouldn't amount to so much (and I doubt you have 1000 interrupts/sec with a single disk)..
Sure, but smallest cache wins. Which is why I thought hpa chose the 3 byte option.
Quoted 1 line
I'm sorry, but the whole effort is misguided, in my opinion.
Respectfully disagree. I wouldn't do it, but it warms my heart that others are. It's are not subtractive from other optimization efforts.
Cheers,
Rusty.
Quoted 12 lines · Rusty Russell
Quoted 10 lines · On Sunday 30 November 2008 04:52:41 Avi Kivity wrote:
Quoted 5 lines · Alexander van Heukelum
I now did the benchmarks for the same -rc6 with hpa's 4-byte stubs too. Same machine. It's significantly better than the other two options in terms of speed. It takes about 7% less cpu to handle the interrupts. (0.64% cpu instead of 0.69%.) I have to run now, I'll let interpreting the histogram to someone else ;).
This is noise. 0.05% cpu on a 1GHz machine servicing 1000 interrupt/sec boils down to 500 cycles/interrupt. These changes shouldn't amount to so much (and I doubt you have 1000 interrupts/sec with a single disk)..
Quoted 7 lines
Sure, but smallest cache wins. Which is why I thought hpa chose the 3 byte option.
Quoted 1 line
I'm sorry, but the whole effort is misguided, in my opinion.
Respectfully disagree. I wouldn't do it, but it warms my heart that others are. It's are not subtractive from other optimization efforts.
Yeah, the efforts from Alexander, Peter and Cyrill are fantastic.
The most positive effects of it isnt just the optimizations and code compression. What is important is the fact that this piece of code (entry_*.S) has not gotten systematic attention for a decade, and has become a rather crufty patchwork of hit-and-run changes. It has become very hard to review and it has become a reoccuring source of nasty bugs.
It is now being reworked and re-measured. It does not matter how small and hard to measure the gain is in one specific case - we are mainly concerned about not creating measurable _harm_, and we are after the cleanups and the increase in maintainability. Once the code is cleaner, improvements are much easier to do and bugs are much easier to fix.
Ingo
Quoted 10 lines · Rusty Russell
Quoted 8 lines · On Sunday 30 November 2008 04:52:41 Avi Kivity wrote:
Quoted 6 lines · Alexander van Heukelum
I now did the benchmarks for the same -rc6 with hpa's 4-byte stubs too. Same machine. It's significantly better than the other two options in terms of speed. It takes about 7% less cpu to handle the interrupts. (0.64% cpu instead of 0.69%.) I have to run now, I'll let interpreting the histogram to someone else ;).
Quoted 8 lines
Quoted 4 lines
This is noise. 0.05% cpu on a 1GHz machine servicing 1000 interrupt/sec boils down to 500 cycles/interrupt. These changes shouldn't amount to so much (and I doubt you have 1000 interrupts/sec with a single disk)..
Sure, but smallest cache wins. Which is why I thought hpa chose the 3 byte option.
Four bytes was the smallest sane option. Three bytes involved instruction opcodes overlap.
Quoted 5 lines
Quoted 2 lines
I'm sorry, but the whole effort is misguided, in my opinion.
Respectfully disagree. I wouldn't do it, but it warms my heart that others are. It's are not subtractive from other optimization efforts.
Once it's done there's no reason not to commit it. But the effort expended to do it is gone, without any measurable return.
Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain.
On Mon, Dec 1, 2008 at 12:24 PM, Avi Kivity <[email protected]> wrote:
...
Quoted 5 lines
Once it's done there's no reason not to commit it. But the effort expended to do it is gone, without any measurable return.
...
Not sure Avi what you mean but as far as I know Alexander is working on this file so he need just time to finish (we all have other duties you know :). So I think the idea Peter proposed could be merged right after Alexander will have finished. At least the Peter's suggestion was recorded in this thread which means it will *not* be lost eventually. Or you meant something else (yep, I could have it translated plain wrong)?
Quoted 7 lines · Cyrill Gorcunov
On Mon, Dec 1, 2008 at 12:24 PM, Avi Kivity <[email protected]> wrote:
...Quoted 4 lines
Once it's done there's no reason not to commit it. But the effort expended to do it is gone, without any measurable return.
Quoted 9 lines
...
Not sure Avi what you mean but as far as I know Alexander is working on this file so he need just time to finish (we all have other duties you know :). So I think the idea Peter proposed could be merged right after Alexander will have finished. At least the Peter's suggestion was recorded in this thread which means it will *not* be lost eventually. Or you meant something else (yep, I could have it translated plain wrong)?
What I mean is that hpa's patch makes the kernel better, so it should be applied. I'm not sure what else Alexander is working on, but I do hope the improvements will be more concrete.
(Alexander, I apologise for being so discouraging; but I really feel these improvements are marginal)
Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain.
Quoted 18 lines · Avi Kivity
Quoted 7 lines · Cyrill Gorcunov
On Mon, Dec 1, 2008 at 12:24 PM, Avi Kivity <[email protected]> wrote:
...Quoted 4 lines
Once it's done there's no reason not to commit it. But the effort expended to do it is gone, without any measurable return.
Quoted 9 lines
...
Not sure Avi what you mean but as far as I know Alexander is working on this file so he need just time to finish (we all have other duties you know :). So I think the idea Peter proposed could be merged right after Alexander will have finished. At least the Peter's suggestion was recorded in this thread which means it will *not* be lost eventually. Or you meant something else (yep, I could have it translated plain wrong)?
Quoted 3 lines
What I mean is that hpa's patch makes the kernel better, so it should be applied. I'm not sure what else Alexander is working on, but I do hope the improvements will be more concrete.
that is what happened three weeks ago already on Nov 11, we applied Peter's patches to tip/x86/irq:
939b787: x86: 64 bits: shrink and align IRQ stubs
b7c6244: x86: 32 bits: shrink and align IRQ stubs
it's all in the x86 tree and in linux-next as well. Alexander and Peter are working on this together, not against each other. Alexander was still running some numbers to make sure we made the right decision.
Ingo
Quoted 6 lines · Alexander van Heukelum
I now did the benchmarks for the same -rc6 with hpa's 4-byte stubs too. Same machine. It's significantly better than the other two options in terms of speed. It takes about 7% less cpu to handle the interrupts. (0.64% cpu instead of 0.69%.) I have to run now, I'll let interpreting the histogram to someone else ;).
This is noise. 0.05% cpu on a 1GHz machine servicing 1000 interrupt/sec boils down to 500 cycles/interrupt. These changes shouldn't amount to so much (and I doubt you have 1000 interrupts/sec with a single disk)..
I'm sorry, but the whole effort is misguided, in my opinion. If you want to optimize, try reducing the number of interrupts that occur rather than saving a few cycles in the interrupt path.
Signature · 2 lines
I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain.
Quoted 9 lines · Alexander van Heukelum
Hi all,
I have spent some time trying to find out how expensive the segment-switching patch was. I have only one computer available at the time: a "Sempron 2400+", 32-bit-only machine.
Measured were timings of "hackbench 10" in a loop. The average was taken of more than 100 runs. Timings were done for two seperate boots of the system.
hackbench is _way_ too noisy to measure such cycle-level differences as irq entry changes cause. It also does not really stress interrupts
- it only stresses networking, the VFS and the scheduler.
a better test might have been to generate a ton of interrupts, but even then it's _very_ hard to measure it properly. The best method is what i've suggested to you early on: run a loop in user-space and observe irq costs via RDTSC, as they happen. Then build a histogram and compare the before/after histogram. Compare best-case results as well (the first slot of the histogram), as those are statistically much more significant than a noisy average.
Measuring such things in a meaningful way is really tricky business. Using hackbench to measure IRQ entry micro-costs is like trying to take a photo of a delicate flower at night, by using an atomic bomb as the flash-light: you certainly get some sort of effect to report, but there's not many nuances left in the picture to really look at ;-)
Ingo
Quoted 10 lines · Ingo Molnar
Quoted 9 lines · Alexander van Heukelum
Hi all,
I have spent some time trying to find out how expensive the segment-switching patch was. I have only one computer available at the time: a "Sempron 2400+", 32-bit-only machine.
Measured were timings of "hackbench 10" in a loop. The average was taken of more than 100 runs. Timings were done for two seperate boots of the system.
Hi Ingo,
I guess you just stopped reading here?
Quoted 6 lines
hackbench is _way_ too noisy to measure such cycle-level differences as irq entry changes cause. It also does not really stress interrupts
- it only stresses networking, the VFS and the scheduler.a better test might have been to generate a ton of interrupts, but even then it's _very_ hard to measure it properly.
I should have presented the second benchmark as the first I guess. I really just used hackbench as a workload. I gathered it would give a good amount of exceptions like page faults and maybe others. It would be nice to have a simple debug switch in the kernel to make it generate a lot of interrupts, though ;).
Quoted 6 lines
The best method is
what i've suggested to you early on: run a loop in user-space and observe irq costs via RDTSC, as they happen. Then build a histogram and compare the before/after histogram. Compare best-case results as well (the first slot of the histogram), as those are statistically much more significant than a noisy average.
See the rest of the mail you replied to and its attachment. I've put the programs I used and the histogram in
http://heukelum.fastmail.fm/irqstubs/
I think rdtsctest.c is pretty much what you describe.
Greetings,
Alexander
Quoted 7 lines
Measuring such things in a meaningful way is really tricky business. Using hackbench to measure IRQ entry micro-costs is like trying to take a photo of a delicate flower at night, by using an atomic bomb as the flash-light: you certainly get some sort of effect to report, but there's not many nuances left in the picture to really look at ;-)
Ingo
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - Same, same, but different...
Quoted 8 lines · Alexander van Heukelum
Quoted 7 lines · Ingo Molnar
Quoted 6 lines · Alexander van Heukelum
Hi all,
I have spent some time trying to find out how expensive the segment-switching patch was. I have only one computer available at the time: a "Sempron 2400+", 32-bit-only machine.
Quoted 7 lines
Quoted 3 lines
Quoted 3 lines
Measured were timings of "hackbench 10" in a loop. The average was taken of more than 100 runs. Timings were done for two seperate boots of the system.
Hi Ingo,
I guess you just stopped reading here?
yeah, sorry! You describe and did exactly the kind of histogram that i wanted to see done ;-)
I'm not sure i can read out the same thing from the result though. Firstly, it seems the 'after' histograms are better, because there the histogram shifted towards shorter delays. (i.e. lower effective irq entry overhead)
OTOH, unless i'm misreading them, it's a bit hard to compare them
visually: the integral of the histograms does not seem to be constant, they dont seem to be normalized.
It should be made constant for them to be comparable. (i.e. the total number of irq hits profiled should be equal - or should be normalized with the sum after the fact)
Ingo
Quoted 13 lines · Ingo Molnar
Quoted 12 lines · Alexander van Heukelum
Quoted 10 lines · Ingo Molnar
Quoted 9 lines · Alexander van Heukelum
Hi all,
I have spent some time trying to find out how expensive the segment-switching patch was. I have only one computer available at the time: a "Sempron 2400+", 32-bit-only machine.
Measured were timings of "hackbench 10" in a loop. The average was taken of more than 100 runs. Timings were done for two seperate boots of the system.
Quoted 6 lines
Quoted 3 lines
Hi Ingo,
I guess you just stopped reading here?
yeah, sorry! You describe and did exactly the kind of histogram that i wanted to see done ;-)
I thought so ;).
Quoted 8 lines
I'm not sure i can read out the same thing from the result though. Firstly, it seems the 'after' histograms are better, because there the histogram shifted towards shorter delays. (i.e. lower effective irq entry overhead)
OTOH, unless i'm misreading them, it's a bit hard to compare them
visually: the integral of the histograms does not seem to be constant, they dont seem to be normalized.
The total number of measured intervals (between two almost-adjacent rdtsc's) is exactly the same for all histograms (10^10). Almost all measurements are of the "nothing happened" type, i.e., around 11 clock cycles on this machine. The user time spent inside the rdtsctest program is almost independent of the load, but it measures time spent outside of the program... But what should be attributed to what effect is unclear to me at the moment.
Quoted 3 lines
It should be made constant for them to be comparable. (i.e. the total number of irq hits profiled should be equal - or should be normalized with the sum after the fact)
Basically the difference between the "idle" and "hack10" versions should indicate the effect of extra interrupts (timer) and additional exceptions and cache effects due to context switching.
Thanks,
Alexander
Quoted 1 line
Ingo
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - I mean, what is it about a decent email service?
H. Peter Anvin
reviewerQuoted 5 lines · Alexander van Heukelum
Quoted 4 lines
OTOH, unless i'm misreading them, it's a bit hard to compare them
visually: the integral of the histograms does not seem to be constant, they dont seem to be normalized.
Quoted 8 lines
The total number of measured intervals (between two almost-adjacent rdtsc's) is exactly the same for all histograms (10^10). Almost all measurements are of the "nothing happened" type, i.e., around 11 clock cycles on this machine. The user time spent inside the rdtsctest program is almost independent of the load, but it measures time spent outside of the program... But what should be attributed to what effect is unclear to me at the moment.
I believe you need to remove the obvious null events at the low end (no interrupt happened) and renormalize to the same scale for the histograms to make sense.
As it is, the difference in the number of events that actually matters dominate the graphs; for example, there are 142187 events >= 12 in hack10ticks, but 136533 in hack10ticks_hpa.
-hpa
H. Peter Anvin
reviewerOkay, after spending most of the day trying to get something that isn't completely like white noise (interesting problem, otherwise I'd have given up long ago) I did, eventually, come up with something that looks like it's significant. I did a set of multiple runs, and am looking for the "waterfall points" in the cumulative statistics.
http://www.zytor.com/~hpa/baseline-hpa-3000-3600.pdf
This particular set of data points was gathered on a 64-bit kernel, so I didn't try the segment technique.
It looks to me that the collection of red lines is enough to the left of the black ones that one can assume there is a significant effect, probably by about a cache miss worth of time.
-hpa
Quoted 6 lines · H. Peter Anvin
Okay, after spending most of the day trying to get something that isn't completely like white noise (interesting problem, otherwise I'd have given up long ago) I did, eventually, come up with something that looks like it's significant. I did a set of multiple runs, and am looking for the "waterfall points" in the cumulative statistics.
Quoted 8 lines
http://www.zytor.com/~hpa/baseline-hpa-3000-3600.pdf
This particular set of data points was gathered on a 64-bit kernel, so I didn't try the segment technique.
It looks to me that the collection of red lines is enough to the left of the black ones that one can assume there is a significant effect, probably by about a cache miss worth of time.
This graph is a little confusing. Is the area under each curve here supposed to be a constant?
Is this latency from all interrupts as seen by userspace? Or does a particular interrupt dominate?
Signature · 1 line
Mathematics is the supreme nostalgia of our time.
H. Peter Anvin
reviewerQuoted 12 lines · Matt Mackall
Quoted 11 lines · H. Peter Anvin
Okay, after spending most of the day trying to get something that isn't completely like white noise (interesting problem, otherwise I'd have given up long ago) I did, eventually, come up with something that looks like it's significant. I did a set of multiple runs, and am looking for the "waterfall points" in the cumulative statistics.
http://www.zytor.com/~hpa/baseline-hpa-3000-3600.pdf
This particular set of data points was gathered on a 64-bit kernel, so I didn't try the segment technique.
Quoted 7 lines
Quoted 3 lines
It looks to me that the collection of red lines is enough to the left of the black ones that one can assume there is a significant effect, probably by about a cache miss worth of time.
This graph is a little confusing. Is the area under each curve here supposed to be a constant?
No, they reflect individual runs. They start at 1 at the top left and drop to 0 at the far right in each case. What matters is the horizontal position of large vertical drops.
Quoted 3 lines
Is this latency from all interrupts as seen by userspace? Or does a particular interrupt dominate?
All interrupts, but rather inherently the difference between interrupt handlers is going to be bigger than the differences between implementations of the same handler. I *believe* all the interrupts you're seeing in that graph are probably timer interrupts. The other major interrupt source that was active on the system was USB.
-hpa
Quoted 17 lines · H. Peter Anvin
Quoted 16 lines · Matt Mackall
Quoted 14 lines · H. Peter Anvin
Okay, after spending most of the day trying to get something that isn't completely like white noise (interesting problem, otherwise I'd have given up long ago) I did, eventually, come up with something that looks like it's significant. I did a set of multiple runs, and am looking for the "waterfall points" in the cumulative statistics.
http://www.zytor.com/~hpa/baseline-hpa-3000-3600.pdf
This particular set of data points was gathered on a 64-bit kernel, so I didn't try the segment technique.
It looks to me that the collection of red lines is enough to the left of the black ones that one can assume there is a significant effect, probably by about a cache miss worth of time.
Quoted 7 lines
Quoted 3 lines
This graph is a little confusing. Is the area under each curve here supposed to be a constant?
No, they reflect individual runs. They start at 1 at the top left and drop to 0 at the far right in each case. What matters is the horizontal position of large vertical drops.
Still confused. If, say, the top blue line on the left represents the same number of interrupts as the bottom red one, then at some point it must cross under the red one as it goes to the right, which it does not appear to do. Thus, it does not appear the scale on the left is actually in units of constant probability, no?
Though I'll agree that even if they're not scaled so that the area under the curve sums to a probability of 1, the centerpoint of the vertical drop is what matters. But that's rather hard to read off this chart, as the blue line I mentioned has a center point point well above the red one, so while it looks like a shift of 80 cycles, it's more like 30.
Is there any theoretical reason you can't just sum the histograms for runs of the same code and then divide by event count? Is there some sort of alignment/cache-coloring issue across boots?
Quoted 9 lines
Quoted 3 lines
Is this latency from all interrupts as seen by userspace? Or does a particular interrupt dominate?
All interrupts, but rather inherently the difference between interrupt handlers is going to be bigger than the differences between implementations of the same handler. I *believe* all the interrupts you're seeing in that graph are probably timer interrupts. The other major interrupt source that was active on the system was USB.
That's what I'd expect on an idle system, certainly.
Anyway, I'm actually surprised your red graph is visibly better than your blue one. FWIW, I was leaning towards your simpler variant (and away from the magical segment register proposal). I'd be happy to see either of your versions submitted.
Signature · 1 line
Mathematics is the supreme nostalgia of our time.
H. Peter Anvin
reviewerQuoted 17 lines · Matt Mackall
Quoted 4 lines
Quoted 1 line
No, they reflect individual runs. They start at 1 at the top left and drop to 0 at the far right in each case. What matters is the horizontal position of large vertical drops.
Still confused. If, say, the top blue line on the left represents the same number of interrupts as the bottom red one, then at some point it must cross under the red one as it goes to the right, which it does not appear to do. Thus, it does not appear the scale on the left is actually in units of constant probability, no?
Though I'll agree that even if they're not scaled so that the area under the curve sums to a probability of 1, the centerpoint of the vertical drop is what matters. But that's rather hard to read off this chart, as the blue line I mentioned has a center point point well above the red one, so while it looks like a shift of 80 cycles, it's more like 30.
Quoted 4 lines
Is there any theoretical reason you can't just sum the histograms for runs of the same code and then divide by event count? Is there some sort of alignment/cache-coloring issue across boots?
The reason for the multiple curves is to show the range of uncertainty.
There are three sets of graphs in there: black (current mainline, 16-byte stubs), red (4-byte stubs with a double jump), and blue (8-byte stubs.)
The fact that the system is idle is pretty much a case which should favor "blue" over "red"; realistically I think the graphs show that they are identical within the limits of measurement, and both are significantly better than "black".
Since this is pretty much the optimal case for "blue" and it doesn't show any performance win over "red", I implemented the "red" option and pushed it into tip:x86/irq.
Quoted 6 lines
That's what I'd expect on an idle system, certainly.
Anyway, I'm actually surprised your red graph is visibly better than your blue one. FWIW, I was leaning towards your simpler variant (and away from the magical segment register proposal). I'd be happy to see either of your versions submitted.
Same here, which is why I wanted to check them both out.
-hpa
Quoted 11 lines · Alexander van Heukelum
Quoted 3 lines
OTOH, unless i'm misreading them, it's a bit hard to compare them
visually: the integral of the histograms does not seem to be constant, they dont seem to be normalized.The total number of measured intervals (between two almost-adjacent rdtsc's) is exactly the same for all histograms (10^10). Almost all measurements are of the "nothing happened" type, i.e., around 11 clock cycles on this machine. The user time spent inside the rdtsctest program is almost independent of the load, but it measures time spent outside of the program... But what should be attributed to what effect is unclear to me at the moment.
a high-pass filter should be applied in any case, to filter out the "nothing happened" baseline. Eliminating every delta below 500-1000 cycles would do the trick i think, all IRQ costs are at least 1000 cycles.
then a low-pass filter should be applied to eliminate non-irq noise such as scheduling effects or expensive irqs (which are both uninteresting to such analysis).
and then _that_ double-filtered dataset should be normalized: the number of events should be made the same. (just clip the larger dataset to the length of the smaller dataset)
Quoted 7 lines
Quoted 3 lines
It should be made constant for them to be comparable. (i.e. the total number of irq hits profiled should be equal - or should be normalized with the sum after the fact)
Basically the difference between the "idle" and "hack10" versions should indicate the effect of extra interrupts (timer) and additional exceptions and cache effects due to context switching.
i was only looking at before/after duos, for the same basic type of workload. Idle versus hackbench is indeed apples to oranges.
Ingo
H. Peter Anvin
reviewerQuoted 6 lines · Ingo Molnar
* Alexander van Heukelum <[email protected]> wrote:
hackbench is _way_ too noisy to measure such cycle-level differences as irq entry changes cause. It also does not really stress interrupts
- it only stresses networking, the VFS and the scheduler.
Quoted 8 lines
a better test might have been to generate a ton of interrupts, but even then it's _very_ hard to measure it properly. The best method is what i've suggested to you early on: run a loop in user-space and observe irq costs via RDTSC, as they happen. Then build a histogram and compare the before/after histogram. Compare best-case results as well (the first slot of the histogram), as those are statistically much more significant than a noisy average.
For what it's worth, I tested this out, and I'm pretty sure you need to run a uniprocessor configuration (or system) for it to make sense -- otherwise you end up missing too many of the interrupts. I first tested this on an 8-processor system and, well, came up with nothing.
I'm going to try this later on a uniprocessor, unless Alexander beats me to it.
-hpa
Quoted 16 lines · H. Peter Anvin
Quoted 6 lines · Ingo Molnar
* Alexander van Heukelum <[email protected]> wrote:
hackbench is _way_ too noisy to measure such cycle-level differences as irq entry changes cause. It also does not really stress interrupts
- it only stresses networking, the VFS and the scheduler.Quoted 8 lines
a better test might have been to generate a ton of interrupts, but even then it's _very_ hard to measure it properly. The best method is what i've suggested to you early on: run a loop in user-space and observe irq costs via RDTSC, as they happen. Then build a histogram and compare the before/after histogram. Compare best-case results as well (the first slot of the histogram), as those are statistically much more significant than a noisy average.
Quoted 7 lines
For what it's worth, I tested this out, and I'm pretty sure you need to run a uniprocessor configuration (or system) for it to make sense -- otherwise you end up missing too many of the interrupts. I first tested this on an 8-processor system and, well, came up with nothing.
I'm going to try this later on a uniprocessor, unless Alexander beats me to it.
I did the rdtsctest again for the irqstubs patch you sent. The data is at http://heukelum.fastmail.fm/irqstubs/ and the latency histogram is http://heukelum.fastmail.fm/irqstubs/latency_hpa.png
Greetings,
Alexander
Quoted 1 line
-hpa
Signature · 5 lines
Alexander van Heukelum [email protected] -- http://www.fastmail.fm - Same, same, but different...
H. Peter Anvin
reviewerQuoted 5 lines · Alexander van Heukelum
I did the rdtsctest again for the irqstubs patch you sent. The data is at http://heukelum.fastmail.fm/irqstubs/ and the latency histogram is http://heukelum.fastmail.fm/irqstubs/latency_hpa.png
Okay, I've stared at a bunch of different transformations of this data and I'm starting to think that it's getting lost in the noise. The difference between your "idleticks" and "idleticks2" data sets, for example, is as big as the differences between any two data sets that I can see.
Just for reference, see this graph where I have filtered out events outside the [30..1000] cycle range and renormalized.
http://www.zytor.com/~hpa/hist.pdf
I don't know how to even figure out what a realistic error range looks like, other than repeating each run something like 100+ times and do an "eye chart" kind of diagram.
-hpa
[Andi Kleen - Tue, Nov 04, 2008 at 06:05:01PM +0100]
| > not taking into account the cost of cs reading (which I | > don't suspect to be that expensive apart from writting, | | GDT accesses have an implied LOCK prefix. Especially | on some older CPUs that could be slow. | | I don't know if it's a problem or not but it would need | some careful benchmarking on different systems to make sure interrupt | latencies are not impacted. | | Another reason I would be also careful with this patch is that | it will likely trigger slow paths in JITs like qemu/vmware/etc. | | Also code segment switching is likely not something that | current and future micro architectures will spend a lot of time optimizing. | | I'm not sure that risk is worth the small improvement in code | size. | | An alternative BTW to having all the stubs in the executable | would be to just dynamically generate them when the interrupt | is set up. Then you would only have the stubs around for the | interrupts which are actually used. | | -Andi |
Thanks a lot for comments, Andi!
- Cyrill -