[an error occurred while processing this directive]
ELF is a standard format for executables. An ELF file consists of several sections, each containing either data or code. The beginning of an ELF file contains a header describing the sections, their type, contents, address and length in the file, and the address they are to be mapped to. ELF is described in man pages (type ``man a.out'' on a Solaris box).
The "dit" command which you use to create your boot image copies arbitrary files into the image (have a look at your Makefile). As long as your OS is not able to execute proper ELF binaries, a hack is required to allow in-place execution. This is also done in the Makefile, by the sequence:
The answer to this is now obvious from the above: Your Makefile shows how the -T option is used. The dit -l $(IMAGE) sequence is no longer required, as you are now able to execute ELF files linked to arbitrary addresses. Typically operating systems use a start address in the first page of the virtual address space, hence -T 0x1000.
Note also that loading will no longer done by dit, this is now the job of your OS's loader. This is why we have supplied you with sample code for reading ELF files. Feel free to have a look at the source for dit which can be found in the L4/MIPS source tree. It contains everything you need ;-)
As a consequence of the above you need to specify the -f
flag with dit to stop it from behaving as a loader.
The network driver allocates buffer space in the ``free'' RAM area. You'll need to give it time to do this. Therefore you should not claim any free RAM until you know that the driver (and all other initial servers) are properly initialised. The safest way to do is to wait until you have communicated with it for the first time (i.e., sent a message to it. Note that you don't need to wait for a reply message from the driver.)
Also, as a general rule, do not touch any of the pages in the DIT image, expect the ones belonging to your own executable, or the any of your client executable/files.
If you claim a page which belongs to another initial server,
that server will get live-locked on page faults to sigma0.
On first receive (the first time a bound socket receives a msg) it will try and send an empty string dope from the IPDRIVER_TID. If this msg doesn't get received properly, the driver seems to hang. Every subsequent msg will be dropped (if the first msg is not received properly).
Sorry, we screwed up. The TID is now fixed in ipdriver.h.
If first msg is received properly, each subsequent msg will be from IPSENDER_TID. Also, any send msg, the first few will be dropped, (four for our case). The driver doesn't like too many packet to be sent quickly.
Correct, and totally consistent with the specification. UDP is unreliable.
Thirdly, do not use port 3221... apparently it was use as the reboot msg (or something).
Yes. Sorry, that should have been documented.
The buffer is a local variable in the printfs function of the sample code, hence it is allocated on the stack. The sample code starts the printer thread with a stack of 1kB. If the buffer is made too big, the stack overflows, and evil things happen. Remember, you're the OS, and you haven't implemented memory protection yet, have you? ;-)
Cure: Declare the buffer "static" and it won't be on the
stack. But note that the buffer then becomes a global variable
(although restricted to the scope of the function in which it is
declared). This means that concurrent invocations of the
printfs function (from different client threads) will then
share the buffer. Hence you'll get more evil results if you allow
concurrent calls to printfs.
There are two bits governing the operation of the L4_FPAGE_UNMAP system call. One determines whether the page is completely unmapped or only made read-only. Specify either L4_FP_REMAP_PAGE or L4_FP_FLUSH_PAGE for this.
The second bit determines whether the page is flushed (i.e. removed from client address spaces) or unmapped (i.e. removed from the caller's address space as well). Specify either L4_FP_OTHER_SPACES or L4_FP_ALL_SPACES for this.
Most likely you want to use
This can be done when in kernel debug mode. Use the
command to change the tcb base to the task that you want to view.
(An easy way to find the value of the tcb base that you are interested in
is to put an assert in that task. The kernel debugger will print out
the tcb base of the task that caused the break).
pgpt to see the page table entries.
The following is an example of the output format:
v = 0x78000 pte0 = 0x0 pte1 = 0x79580
The first term is the virtual address and the next two are corresponding page table entries (first is for even, second for odd pages).
The format of each page table entry is:
So for the example above, virtual page 78 is unmapped while virtual page
79 is mapped to physical frame 79.
According to the reference manual, Word 0 of the message contains the R4x00 cause register, word 1 contains the program counter value at the time of the fault, and word 2 contains the address which caused the fault.
The cause register has the following format:
|BD||31-31||Indicates whether the last exception taken occured in a branch delay slot (1="yes").|
|CE||29-28||Coprocessor unit number referenced when a "Coprocessor Unusuable" exception is taken.|
|IP||8-8||Indicates whether an interrupt is pending (1="yes").|
|Code||6-2||Exception code (see below).|
The exception code values are as follows:
|1||Mod||TLB modification exception|
|2||TLBL||TLB exception (load or instruction fetch)|
|3||TLBS||TLB exception (store)|
|4||AdEL||Address error exception (load or instruction fetch)|
|5||AdES||Address error exception (store)|
|6||IBE||Bus error exception (instruction fetch)|
|7||DBE||Bus error exception (date reference: load or store)|
|10||RI||Reserved instruction exception|
|11||CpU||Coprocessor Unusable exception|
|12||Ov||Arithmetic Overflow exception|
Address errors are most likely due to unaligned addresses or
attempts to access kernel-reserved (kseg) memory from user-level.
If so, then must not L4 maintain internally one complete page table per task, plus, ... a frame table?
When a TLB fault occurs, L4 will reload the TLB from its page tables. If there is no mapping for the faulting page in the page table, it will invoke the faulting thread's pager.
Yes, L4 maintains a page table per task. Remember, an L4 task is essentially an address space. And an address space is defined by a page table. You always need one page table per address space.
Consequently, there is some redundancy. Remember, L4 supports recursively constructed address spaces, i.e. address space which get their pages from parent spaces. Obviously, this must be reflected by a corresponding hierarchy of page tables.
How much duplication there actually is depends on what exactly
you are doing. Remember, L4 only knows about RAM, so its page
tables only map pages which are resident. You OS will eventually
map non-resident pages as well, and therefore your page tables will
contain stuff that's not in L4's page tables. On the other hand,
your page tables do not need to contain some of the stuff usually
found in page tables, because L4 takes care of this. (E.g. you
don't need to store TLB entries).
Pagefault and exception IPC is like any other IPC, it adheres to the
The order of the object files specfied in the linking command DOES
matter. /home/disy/l4/lib/crt[0S].o must be first on the line,
followed by your object files, then followed by -lc (libc.a) and
It fails as those tasks are already running and you are not the
chief of them. Task 0 is the nil id, task 1 is sigma zero, task 3 is the
serial port server, and task 4 is likely to be SOS in your case.
dit currently only supports data files greater than 15
bytes in size. Simply pad your file with extra bytes to work around the
For more details:
It means that the page fault happens during a system call, when L4
tries to access user data (e.g. during a long IPC operation). You
probably have a string dope pointing to the wrong place.
It means that you are trying to access kernel-reserved memory. The most likely reasons for this are:
To eliminate these error messages, make certain that all pointers are properly initialised. Use assert(p) if in doubt.
Also make sure you are not overflowing your stack. It is safest not
to put arrays or large records on the stack, declare them as
static. Note that you can use the static storage
class also for a function's local variables, that way you do not
lose the locality local variables give you. However, be aware that
you may have to use concurrency control on local static variables
if the function can be called from different threads.
It means that the address of the message header, divided by four, is stored. Of course, dviding by four just means chopping off the two least significant bits, which leaves 62. This is just a way of saying that only the leading 62 bits of the address are stored. Which is fair enough, as the message descriptor must be word (i.e. 8-bit) aligned, which ensures that the three least significant bits of the address are zero and do not need to be specified. L4 makes use of this to use those bits for the m (mapping) and d (deceiving) flags.
You actually don't need to worry about this, as you're using the C library interface. That one automatically masks in the d bit if you are using a deceiving version of the system call interface, you just pass the message header address to that function.
How the m-flag gets set can be seen in the pager example.
No. The serial port driver will output data passed the registers
until it encounteres a null byte or has processed all data. Hence
if you want to send a string of 64 bytes you can do this in a
void *rcv_msg is an input, not an output parameter to the system call. It passes to L4 a message descriptor which describes where to store the IPC message. L4 expects that parameter to point to a properly set up message header (followed by appropriate buffer space and string dopes).
The only output parameters in the IPC system call(s) are
rcv_reg, which points to a buffer receiving the
in-register part of the message, and result which returns
the result status and the number of words of in-line data and
strings delivered in the message.
For practical questions on how to use L4, consult the L4 User Manual. The most definite reference is the L4 Reference Manual, however, this does not explain everything you need to use L4. We are working on improving the reference manual, and also on a user's manual.
More general information on L4 can be obtained from a number of technical publications, in particular