Logo Umeet2001

ESPAÑOL
Presentación

Programa

Desarrollo

ENGLISH

Presentation

Programa

Desarrollo


rielok, welcome to today's evening lecture
rielthis lecture will be given by William Irwin, who works for IBM in the US
rielnow, you know I'm a kernel guy .. but the subject of today's lecture is magic for me, too
rielWilliam Irwin (wli) will be talking about how machines in the i386 machine boot
rielthe word booting comes (I think) from bootstrapping, or pulling yourself up by your boots
riela typical maneuvre for cartoon charactors ;)
wliAlrighty.
rielsince I have no idea how this magic procedure would ever work, I guess I'll turn over the channel to wli
viXardeasy pal ;)
wliWell, I want to give the perspective from the kernel as to what is required to make a machine run on i386.
wliNow, the i386 is an elaborate architecture, so I can only cover a few aspects of this.
JALHhah, elaborate? crap more-ike
JALHs/ike/like/
wliAnd these are largely the aspects required for a kernel to run on any architecture.
wliA fairly simplified model of a system booting is the following:
wli(1) the kernel is loaded
wli(2) the kernel initializes the state of CPU, especially the registers.
wli(3) the kernel enables virtual addressing or paging
wli(4) the kernel prepares itself to handle exceptions and interrupts
wli(5) the kernel initializes parts of the machine so that interrupts (exceptions generated by external devices) are actually sent to it
wli(6) discovering devices and initializing them
wli(7) loading the initial programs from storage devices and starting up their execution
wliThere is a lot of material there, and I would like to stay at a basic level, so I would like to stick to steps 1-4, and briefly cover parts about 5.
wliOn i386, there are also steps even before (1) in many instances.
JALHcalc:)
calcthx
wliBefore the kernel runs, firmware called a BIOS is the first thing that actually executes on the machine.
wliThe BIOS in turn loads the bootstrap loader from a storage device using platform-specific ways to access hardware, and begins executing it.
JALHbios loads 512 bytes , last 2 bytes of that sector must be 0x55aa or 0xaa55, loads it at 0x7C00 and goes there.. :)
wliThe bootstrap loader then has to find the kernel, and there are a number of ways they interact.
wliFirst, the bootstrap loader has to know how to find the kernel on the storage devices.
JALHoh, the partition table also takes up 64 bytes at the end too
wliLinux itself defines a boot protocol and requires itself to be loaded in a particular location.
calcwith linuxbios all of that could be gotten rid of right?
calcthat isn't a question for wli btw ;)
JALHhm
JALHnot sure about the boot seq of the actual chip before the bios
JALHI think it starts at 0xfff0:0000
calcwell the stuff after the bios would be the same no matter what, aiui
JALHbut linuxbios would have to be able to load doze etc, no?
erikmJALH: that's right. but as soon as linuxbios takes over, you can define your own boot process
asgI thought it was FFFFFFF0 but who cares
JALHah
JALHit could prolly load linux straight then
wliThe example I would like to present uses the ELF multiboot format for an executive (a program that runs with direct hardware access, but is not an OS) that demonstrates some of the formats and required control register initializations a kernel would have to do.
calcthe same process esentially would happen but maybe not the same details
erikmasg: somewhere high up. in real mode but still with the CS selector mapped in such a way that it can run from that address
JALHyeah
wliThe ELF file format is understood by GRUB, and that is used to control the locations of memory where the kernel is loaded.
wliAnd also to inform GRUB of the kernel's entry point.
wliThere is an important issue that arises when loading a kernel this way:
JALH0xf000:fff0
wliThere is something called an absolute reference, in contrast to a relative reference.
erikmJALH: that's the 8086 entry point
JALHin 'real' terms
wliA relative reference would add an offset to the address of the instruction being executed or a dedicated register.
JALHthis is for a 486
wliBut an absolute reference specifies the entire address as a constant.
JALHnothing at startup has really changed between any of the x86 things :/
JALHbackwards compatable with 1980...
wliThe reason why this is an issue is because a virtual address will be much larger than the physical address.
asgintel SDM vol 3 section 8.1.4
wliFor instance, in Linux, the kernel sees its own machien code above 0xC0000000
wliBut the machine code is far below 3GB, just about 1MB.
erikmJALH: ok, got it. it's indeed 0xf000:fff0, but with the CS selector mapped at the highest 1MB. first long jump will switch the CPU to "real" real mode
JALHhuh..
wliThere is a way to deal with this using the ELF format, and that involves load memory addresses vs. virtual memory addresses.
JALHweird :)
JALHahh
JALHI see
calcif your entry point is f000:fff0 wouldn't cs be highest 64k ?
wliA load memory address is the real address where the program is loaded, and the virtual memory address is where absolute references are generated.
wliThis requires giving special directives to the linker.
JALHyeah
erikmcalc: eh, yeah. that's what I mean %-)
wliAn example:
wliSECTIONS
wli{
wli    .multiboot  0x100000:AT(0x100000)   { *(.multiboot) }
asgHowever, during a hardware reset, the segment
asgselector in the CS register is loaded with F000H and the base address is loaded with
asgFFFF0000H. The starting address is thus formed by adding the base address to the value in the
wli    .boot (0x100000+SIZEOF(.multiboot)):AT(0x100000+SIZEOF(.multiboot)) {
wli        *(.boot)
wli    }
wli    .text   (0xC0000000 + 0x100000 + SIZEOF(.boot) + SIZEOF(.multiboot)) :
wli        AT(0x100000 + SIZEOF(.boot)+ SIZEOF(.multiboot) )
wli        { *(.text) }
wli... and so on.
JALH*nod*
calcerikm: heh
JALHwhich I suppose is the ROM
wliBefore the : the VMA is specified, and after, the LMA is specified.
wliCode linked so that the absolute references are above 0xC0000000 can't execute properly until virtual addressing is enabled.
wlic010b0a4 T main
erikmcalc: the 386 is not really the most clean architecture you'd like to learn about...
wliThis is loaded at 0x10b0a4, but when you try to call main, the code generated attempts to go to the address 0xc010b0a4
JALHit boots straight to C, it's amazing
wliThis will not work until paging is enabled, and the mapping from the upper 3GB of the address space is enabled.
calcerikm: yea :\
wliIs created, rather.
calci think they use a different arch for comp org 2
JALHprolly arm
wliUnfortunately, the memory model on i386 is complex.
wliFirst, in order to be able to reference an address, one must reference an address within something called a segment.
erikmJALH: ARM can also boot straight to C
wliThese segments are a backward compatibility feature from Intel machines before the 386.
wliA segment specifies a range of memory and permissions on it. It is a memory protection mechanism based on ranges.
wliThere are segment registers used to control the segment a memory reference uses.
wliThese don't contain the whole information about the segments permission and range.
wliThere is a table called the global descriptor table (GDT) that contains the information about the segments.
erikmJALH: depending on the amount of initialisation you need to do you could be into C code in about 10 instructions
wliThe GDT can contain up to 8192 different 64-bit records describing segments.
JALHcall that booting straight to C? I'm talking it loads and goes to 'main'
JALHI wrote a program to print some strings etc over the serial port and then reboot
JALHwithout a single line of asm
JALH:)
calcnice
calchow does it know which file to run?
asgbootloader?
JALHthe prom on the box loads it via tftp
calcok
wliThe value of an entry in the GDT is computed from the base address of the segment, the size of the segment, and several control flags to specify what kind of segment it is.
JALHin ecoff format
JALHit does all the dirty work
wliIt can be a code segment, a data segment, or a stack segment.
erikmJALH: I could do that as well, but I'd better copy the stuff from flash to ram and setup a stack
wliIt can also be read-only.
JALHhm, setting up a stack
asgwli: but all this GDT stuff is moot because the kernel sets it up then forgets about it
JALHthat might come in handy ;>
JALHhm
JALHthe kernel sets up several gdt's
JALHwell, one in the inital bootloader
JALHthen one in the head.S or something
wliSeveral of the flags control whether the segment is accessible to the kernel or the user, and also have an escape in order to be able to specify things that aren't segments in the GDT.
wliasg: Well, this is about what it does and throws away.
asgwli: ok :)
JALHand in 2.2, each process uses 2 GDT entries
wliFor instance:
erikmasg: I don't have "understanding the linux kernel" at hand, but didn't the GDT contain an entry for each process?
wli#define GDT_SEGMENT_PRESENT_FIELD               BIT(15)
wli#define GDT_SEGMENT_AVAILABLE_FIELD             BIT(20)
wli#define GDT_SEGMENT_RESERVED_FIELD              BIT(21)  
wli#define GDT_SEGMENT_DEFAULT_FLAG                BIT(22)  
wli#define GDT_SEGMENT_GRANULARITY_FLAG            BIT(23)  
JALHin 2.2
JALHin 2.4 it has 2 entrys for each CPU
asgerikm: what JALH said
JALHand does soft task switching
erikmJALH: *nod* ok, that was the trick
JALHit's neat
JALHjust save a few reg's then swap the stack
wliOne way to define some segments appropriate for a kernel to execute is:
JALHand fake a ret instruction
wli#define KERNEL_GDT_ENTRY                                                \
wli(                                                                       \
wli        GDT_BASE_ADDRESS_ENCODE(0ULL)                                   \
wli                | GDT_SEGMENT_LIMIT_ENCODE(~0ULL)                       \
wli                | (((unsigned long long)GDT_SEGMENT_PRESENT_FIELD) << 32)\
wli                | (((unsigned long long)GDT_SEGMENT_DEFAULT_FLAG) << 32)\
JALHno
wli                | (((unsigned long long)GDT_SEGMENT_GRANULARITY_FLAG) << 32)\
wli)
JALHhm, been a while since I looked at the code, took me a few days to figure it out
JALH:)
wliAnd then one can do KERNLE_GDT_ENTRY | (GDT_CODE_TYPE << 32) to obtain a code segment or a data segment.
wliWhen a GDT is loaded, the base pointer of the table is not actually stored, but rather a 48-bit record with a base and a length.
wliEssentially:
wlistruct gdt_record
wli{
wli        unsigned short gdt_limit;
wli        unsigned long gdt_address;
wli} __PACKED__;
wliThen definitions like:
wli{
wli        GDT_TABLE_SIZE * sizeof(unsigned long long),
wli        (unsigned long)&global_descriptor_table[0]  
wli};
wliunsigned long long global_descriptor_table[GDT_TABLE_SIZE]
wli{
wli        0ULL,
wli        KERNEL_GDT_CODE_ENTRY,
wli        KERNEL_GDT_DATA_ENTRY,
wli        KERNEL_GDT_DATA_ENTRY,
wli        KERNEL_GDT_DATA_ENTRY,
wli};
wliare possible.
wliNow, the segments themselves are things that must be initialized properly, but are not regularly used apart from where required.
rielmanfred: this is the place to ask questions to wli ;)
wliBut once they are in place, you can begin setting up page tables.
wliThere are several control registers on x86, and they very densely encode information, generally with bit fields of the registers.
wliFor instance, there are bits like:
wli#define CR0_PAGING_ENABLED                      BIT(31)
wli#define CR0_CACHE_DISABLE                       BIT(30)
wliand
wli#define CR4_PHYSICAL_ADDRESS_EXTENSION          BIT(5)
wliIn general, a kernel will want to use a large page size extension in order to give the processor's internal cache for page table entries more room for user programs.
wliThat is, when fewer pages are needed to ddescribe the same amount of memory, this cache (the TLB) will not need to have as many trasnlations inserted to access kernel memory.
wliMy demonstration was tested on a less featureful machine, though, so I will show the kernel using ordinary 4KB pages:
wliThe page table will be 2 levels, and will need to be initialized before the control register is set to the address of the page table .
wlithere is a top level that describes 4MB regions, and it has 1024 entries.
wliAnd there is an array of 1024 entries below each of those that has any translations, that gives the translations for 4KB regions of memory.
wliI set up 16MB starting at 0x00000000 and mapping identically to physical addresses
wliAnd also 16MB starting at 0xC0000000, but that maps to the same 16MB starting at 0x0
wliThese are just arrays of unsigned long with parts of an address in the top bits, and control flags in the bottom bits.
wliSo I use a loop like this:
wli                        ((unsigned long)(&low_page_table_entries[1024U*k]))
wli                        | PAGE_PRESENT_FIELD                              
wli                        | PAGE_SUPERVISOR_FIELD
wli                        | PAGE_WRITABLE_FIELD;
wli                        ((unsigned long)(&high_page_table_entries[1024U*k]))
wli                        | PAGE_PRESENT_FIELD
wli                        | PAGE_SUPERVISOR_FIELD
wli                        | PAGE_WRITABLE_FIELD;
wli        }
wliTo set up the top level.
wliOn top, this happens:
wliOn bottom, rather:
wli                low_page_table_entries[k]
wli                                | PAGE_PRESENT_FIELD
wli                                | PAGE_SUPERVISOR_FIELD
wli                                | PAGE_WRITABLE_FIELD;
wliSo there are now segments and page tables ready for the kernel to use.
wliSpecial instructions, which no compiler will generate, must be used to set the registers for these, though.
wliSpecial hand-coded assembly, movl $kernel_page_table, %cr3 needs to happen.
wliThere is also a special instruction just for loading the GDT.
wliSo I wrote some procedures in assembly, and they do these for me when I call from C:
wli        write_gdt(&gdt_record);
wli        boot_write_cr3((unsigned long)kernel_page_table);
wliBut there is one more step!
wliUnless the flag in %cr0 is set, the page tables installed into %cr3 will not be used.
wli        boot_write_cr0(cr0);
wliAnd now the code linked at virtual addresses can be called.
wli-but-
wliThere is yet another detail, which this example won't need, but something that expects to run user code might:
wliThere is support for older pre-386 machines' hardware task switching.
wliThis support gives the special place where all the registers are saved when an exception is taken a segment all its own.
wliAnd because it's a segment, it must be installed in the GDT.
wliThis is called the Task State Segment (TSS).
wliIt's a large data structure that has places for all of the user registers, and also places for all the control registers.
wliThe choice here is to statically allocate one of these data structures, and to install it in the GDT.
wliSo now, just before write_gdt() is called:
wliBut the task switching mechanism essentially wraps up an execution context in a TSS structure, and allows you to switch between them by doing a few things, and most importantly, setting the %tr control register.
wliThis is not usually a desirable thing to use, so one is set up, and largely ignored there after. But it must be set up!
wli      
wli        write_tr(&task_segment_selector);
JALHwli, you don't /have/ to have a TSS
wliWell, it can be ignored perhaps more than I'm ignoring it, true.
JALHlinux only needs the TSS to do the IOPERM bitmap
wliSMP too.
wlidon't want them dumping state in teh same place
JALHeh? why?
JALHeach processor can just switch stacks, it can all be done via struct task's I think
JALHIE, in sw
wliNow virtual addressing is enabled, and we can call the code linked at virtual addresses.
wliBut there is an important caveat:
wliOne's stack pointer must be a virtual address.
wliTo handle that, the code right at the entry point does this:
wli       call initialize_kernel_virtual_addressing
wli        movl $kernel_stack, %esp
wli        movl $kernel_stack, %ebp
wli        call main
JALHwli, why ebp?
wlibefore the kernel stack move, we are executing code at:
wli001010ec ? initialize_kernel_virtual_addressing
wliand after:
wlic010b0a4 T main
JALH:)
wliThe disassembly shows we really are dereferencing an address in the outer space of 3GB:
wli  10003e:   e8 61 b0 00 c0          call   c010b0a4 <main>
wlimain() simply does         debug_write_unsafe("Hello world!\n");
wliand then         initialize_machine_state();
wliThere are only a couple of things you'd do before starting to interact with devices:
wli(1) set yourself up to be able to handle exceptions and interrupts
wli(2) actually arrange to have them sent to you
wliNow, (1) once again involves a special register pointing to a table.
wliThis table is called the Interrupt Descriptor Table (IDT)
wliEssentially this is a table of function pointers that tell the CPU which function to call when something happens.
wliThe exceptions or interrupts have numerical codes describing what happened.
wliAnd these codes act as indices into that table of function pointers.
wlithe problem is that the call doesn't always communicate the number to you!
wliThere are some exceptions where the code is passed as an argument, but the others are called with no arguments at all.
wliThe way this is handled is that a whole bunch of small functions are defined, one for each code, that do nothing more than pass the code in to another function that does the real work.
wliThe ones that have the code already don't need to do much anyway, but the ones that don't know their number and can set it up as an argument to the real function.
wliNow, since there are 256 different codes, I resorted to using macros.
wliSo bear with me:
wli#define IDT_EXCEPTION_HANDLER_WITH_CODE(EXCEPTION_CODE, EXCEPTION_HANDLER) \
wli        .global idt_entry_##EXCEPTION_CODE ;            \
wli        .type idt_entry_##EXCEPTION_CODE,@function ;    \
wli        .align 4 ;                                      \    
wli        idt_entry_##EXCEPTION_CODE : ;                  \
wli        pushl $(EXCEPTION_HANDLER) ;                    \
wli        jmp raw_synchronous_exception_handler            
wliThere is actually something else going on, too.
wlijmp raw_synchronous_exception_handler does a goto to a common block of assembly code that does the actual call.
wliIn this case, we don't need to use the exception code except as a way to name the function.
wliSince they all need different symbols to be linked.
wliIDT_EXCEPTION_HANDLER_WITHOUT_CODE(ARITHMETIC_EXCEPTION_CODE,
wli                                        arithmetic_exception);
wliThis will define the symbol idt_entry_ARITHMETIC_EXCEPTION_CODE
wliWhich is an ugly name, but that's okay, because it's distinct and not really used anywhere directly.
wliNow these exception handlers must handle segments once again:
wliVarious other parts of the register state may not be saved without some intervention.
wliSo to deal with this before C code is called:
wliraw_synchronous_exception_handler:
wli        cld
wli        pushal                                          
wli        pushw %ds
wli        pushw %es
wli        movw $KERNEL_DATA_SEGMENT, %ax            
wli        movw %ax, %ds
wli        movw %ax, %es
wli        call synchronous_exception_handler
wliDealig with asynchronous exceptions or interrupts is largely similar.
wliCompared to the GDT, the IDT is simple, though.
wliThe addresses of the idt_entry_ functions are encoded in the same way as the GDT, but basically only a couple of extra fields must be put in.
wliThe same way as the GDT encodes segment base addresses that is.
wli#define IDT_ENTRY_ENCODE(SEGMENT, VECTOR)                               \
wli(                                                                       \
wli        (((unsigned long long)IDT_INTERRUPT_GATE_TYPE) << 32)           \
wli        | IDT_CODE_SEGMENT_ENCODE(SEGMENT)                              \
wli        | IDT_VECTOR_ENCODE(VECTOR)                                     \
wli)
wliOnce again, there is a record like the GDT's that describes the starting address and size of the IDT, and so the IDT record contains those and uses the same format.
wliAnd in a big code block, I do:
wli        IDT_ENTRY_INITIALIZE(ARITHMETIC_EXCEPTION);
wli        IDT_ENTRY_INITIALIZE(DEBUGGER_ENTRY_EXCEPTION);
wli        IDT_ENTRY_INITIALIZE(NON_MASKABLE_INTERRUPT_EXCEPTION);
wli... and so on
wliThe asynchronous exceptions start at 32, though, and there aren't any special meanings for their numbers:
wli        IDT_ASYNCHRONOUS_ENTRY_INITIALIZE(32);
wli        IDT_ASYNCHRONOUS_ENTRY_INITIALIZE(33);
wli... up to 47.
wliThen simply:
wli        write_idt(&idt_record);
wliHow am I doing on time?
fernandono problem with time
wliI don't want to run over too long.
fernandoif people is ok ;)
wliI'm running out of time myself, unfortunately.
wliSorry if this is a little rushed, but here goes.
iaioxno problem with time
wliNow, even though we are prepared to deal with exceptions if they are delivered to us, they won't be delivered to us unless the CPU itself has the option bit set that turns on the feature where it makes those function calls when the signals are received.
wliAnd also, the signals must be delivered to us from a device called an interrupt controller.
wliAll of the signals for delivering exceptions from devices go through this interrupt controller.
wliThere is a sort of userland equivalent to this: SIGIO
wliThe part with the IDT is like sigaction(): if we get the signal, we call the handler function.
wliBut now we have to tell the interrupt controller the fcntl() part.
wliThere are two interrupt controllers, and they are tied together.
wlino problem
wliBy using a special instruction to access their memory (actually called registers), you can issue commands to this device.
erikmwli: thanks for the lecture
wliIt's called port I/O.
wlino problem
wliThere are two I/O ports for each of the two twin interrupt controllers:
surrielI'll read the rest of the lecture in teh archive
wliI'm almost out of steam anyway.
JALHnight all, thanks wli :)
JALH(clap clap clap clap clap)
wliEssentially a command and a data port.
wliThe sequence is (1) tell the controller to initialize itself, inform it which interrupts are serviceable, whether it is the slave or if it is the master, where the slave is, and how it receives acknowledgments about the interrupt.
wliI myself wrote:
wli        port_write8(IC0_COMMAND_PORT,   IC_RESET_COMMAND);
wli        port_write8(IC0_DATA_PORT,      IC_VECTORS_SERVED);
wli...
wli        port_write8(IC1_DATA_PORT,      IC_8086_EOI_MODE);
wli        port_write8(IC1_DATA_PORT,      IC_MASK_ALL_INTERRUPTS);
wli...
wliAnd from there, the command to unmask the interrupts should be all you need to start receiving them.
wliOne more important note, but not much detail:
wliThe kernel is required to respond to timing information, and it receives an interrupt at regular intervals from a built-in device.
wliBut that device must be initialized.
wliOtherwise it's all handled in the same way.
wliUnfortunately 3PM is my cutoff limit otherwise I'd go on.
cdubtime for any questions?
wliI can post my example code in a short while.
wliOkay, I'll field a couple of questions before I take off.
cdubwhen you register a device (talking APIC here) is it possible to dictate whether it is XT-PIC or IO_APIC
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
wliYes and no.
cdub;-)
cdubif you cat /proc/interrupts you'll see keyboard for example as XT-PIC
wliIO-APICs can emulate XT-PIC but there is hardware out there that is a real PIC, and can't be treated like an IO-APIC.
wliFor instance, model 1 Athlons.
JALHclap clap clap clap clap clap!
JALH:)
digiobithanks for the class
fernandoplas plas plas plas plas plas plas plas plas plas plas
fernandoplas plas plas plas plas plas plas plas plas plas plas
fernandoplas plas plas plas plas plas plas plas plas plas plas
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
iaioxclap clap clap ... thanks
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
wliIt was pretty basic, but I didn't want to get too far out there.
iaioxthanks a lot
digiobiis there notes or samples on the net?
JALHtook me about 6 months to figure all that out :)
wliI'll get back to the conference coordinators about how to get at the sample code.
cdubthanks wli!  i certainly learned something ;-)
fernandothank you to all for comming
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
MJesus_clap clap clap clap clap clap clap clap clap clap
JALHyou can test for an apic
MJesus_clap clap clap clap clap clap clap clap clap clap
digiobiI learned something
fernandoand thank you to the lecturer for this nice talk
wliThe sample code boots & runs, so it could be worth looking at.
wliyes, but it's difficult.
JALHiirc there's a bit in cr0 or eflags that says there's one, no?
fernandolet us remember that umeet finishes tomorrow
JALHand you can always massage the memory to see if there's one there
wliI don't understand the full details, a lot of it are workarounds for hardware bugs.
digiobiare there lectures in here often?
sarnolddigiobi: well, for a while :)
fernandowell, it depends on people interests
fernandowe had some lectures in june about ipv6, security and so on
sarnoldhttp://umeet.uninet.edu/
fernandoand now, we have had umeet
fernandowhat's next?
fernandowho knows?
fernando;)
JALHmaybe we could have it in real life?
JALH:)
fernandoif you feel that you can organize a talk
Ryback_:)
fernandoand you fell that this place would be ok for your talk
sarnoldah, I thought fernando meant, "what is next lecture in the umeet series?" :)
fernandocome here and tell us
cdubthis isn't real life? ;-)
fernandoI understood he was talking about the future
JALHcdub, hmmm, tough question
JALHI irc therefore I am?
JALH:)
cdubhehe
Ryback_:)
digiobiI'm trying to learn kernel stuff that's why I'm here :-)
cdubwli, THANKS!
digiobiwli thanks a lot
fernandotomorrow there will be a round table on ipv6
JALHdigiobi, see also openprojects.net/#kernelnewbies
wlianytime
fernandoand, later
fernandoa talk on the kernel janitors project
digiobiJALH: I was in there earlier, was pretty quiet.  
JALHdigiobi, wait till someone asks a question ;>
JALHjust wait and soak up knowledge :)
digiobiJALH: hehe,  well I'm interested in learning about Memory Management and task scheduling so hopefully I'll see something.
JALHyep
JALHfor memory, ask a question when riel's around ;>
digiobijahl: i'm starting to slowly go through bits of the linux kernel but getting started is that hard part
sarnold(can someone please check the time for that round table tomorrow? :)
fernandolet me check
MJesus_also come acme, and davej, and jgarzik
MJesus_at 22 CET time
fernandothere was a problem with one of our speakers
JALHah yeah, there's some kernel janitors thing
digiobiwell I enjoyed wli's lecture.  I logged it so I can go over it more later
fernandoand we didn't fix the round table time yet
fernandodigi: we'll publish it in our web also
sarnoldthere, no time now :)
fernandowe'll announce it as soon as possible
digiobifernando: is that the umeet.uninet.edu page you listed earlier?
fernandoyes
digiobifernando: kewl, thx
sarnoldfernando: where are the logs located? :)
fernandoumeet.uninet.edu/umeet2001/english/des.eng.html
VERTIGOhola viZard
digiobiI might have to come back here more often.  I help op #linuxhelp on undernet, but interested in learning the hardcore stuff
viZardhola
fernandothe round table will be at 20:00 CET
sarnoldfernando: gracias :)
fernandoat 22:00 the kernel janitors project talk
sarnoldthere we are :) New time :)
fernando20:00
fernandoat 22:00 is another different one
sarnoldooh :) nice compromise
JALHhehe
fernandolater
fernandosome music and fireworks ?
fernandohehe
JALHproject
digiobiwho was that who gave the lecture?
sarnoldheh, I like 'proyect' more :)
JALHwli?
sarnolddigiobi: wli?
digiobiyeah wli?  
JHolas
sarnold'night JALH :)
IRC log ended Sat Dec 15 01:15

Generated by irclog2html.pl by Jeff Waugh - find it at freshmeat.net!


Mas información: umeet@uninet.edu