Hi,
currently I'm trying to understand how it works in assembly until C starts. Could we divide the stage0_i586.S file into its three parts? Resetvector, Jump to protected mode and the CAR code? Maybe it would be easier to understand and to maintain. With my GeodeGX1 systems I cannot use the mtrr registers to get some memory from the cache. To replace it a complete new file would be required. Maybe it would be better to support different methods how to get CAR and link them on demand?
Juergen
On 5/18/07, Juergen Beisert juergen127@kreuzholzen.de wrote:
Hi,
currently I'm trying to understand how it works in assembly until C starts. Could we divide the stage0_i586.S file into its three parts? Resetvector, Jump to protected mode and the CAR code? Maybe it would be easier to understand and to maintain.
No. We've tried that and it failed badly. I am finding it much easier to deal with 1 file.
Once you start to go down that include path, it gets messy very fast. Trying to solve it with linker hackery only makes it worse.
I also don't think splitting it really eases readability that much. Again, we've tried both ways, and I like the new way best.
With my GeodeGX1 systems I cannot use the mtrr registers to get some memory from the cache. To replace it a complete new file would be required. Maybe it would be better to support different methods how to get CAR and link them on demand?
no linker tricks. GNU bintools are not reliable enough to do anything but the simplest things. Again, this file is carefully designed, based on 7 years experience, to minimize potential problems with GNU tools.
Also, we don't want to make assembly too easy for people. We had a few people do assembly, even where they could have used C. Never again.
thanks, and keep asking questions, and making suggestions, even if we disagree with them :-)
ron
* Juergen Beisert juergen127@kreuzholzen.de [070518 20:53]:
currently I'm trying to understand how it works in assembly until C starts. Could we divide the stage0_i586.S file into its three parts? Resetvector, Jump to protected mode and the CAR code? Maybe it would be easier to understand and to maintain.
If you look in the history of linuxbiosv3 (ie via linuxbios.org/viewvc) you will find that that is the way I implemented it. While this worked fine with new binutils and compiler, some old toolchains terribly broke this when you start to change small things. It was very fragile.
So we changed it. Now it is exactly as fragile, but it is one fragile mess, not three of them.
With my GeodeGX1 systems I cannot use the mtrr registers to get some memory from the cache. To replace it a complete new file would be required. Maybe it would be better to support different methods how to get CAR and link them on demand?
The overhead of the reset vector and switching to protected mode before you enable CAR is 17 instructions (roughly). While you could factor that out, it is at the border between moving the complexity from one side (1 big file) to the other (composing several files and watching the code flow) and the philosophic unseemliness of having to duplicate 17 instructions per cpu type.
I don't really like the way it is done at the moment, working around weird bugs instead of fixing them, and I do quite some ironing out of the weird hacks in "lar". We're not a toolchain project, so we probably have to live with it ;)
Stefan
Hi Stefan,
On Friday 18 May 2007 23:56, Stefan Reinauer wrote:
- Juergen Beisert juergen127@kreuzholzen.de [070518 20:53]:
currently I'm trying to understand how it works in assembly until C starts. Could we divide the stage0_i586.S file into its three parts? Resetvector, Jump to protected mode and the CAR code? Maybe it would be easier to understand and to maintain.
If you look in the history of linuxbiosv3 (ie via linuxbios.org/viewvc) you will find that that is the way I implemented it. While this worked fine with new binutils and compiler, some old toolchains terribly broke this when you start to change small things. It was very fragile.
What do you mean with "old toolchains"? How old? I made some local changes to support my Geode GX1 and I would try it also with older toolchains (currently I'm working with a 4.1.2 cross toolchain).
So we changed it. Now it is exactly as fragile, but it is one fragile mess, not three of them.
My question is: What is fragile in this code? To get the correct opcodes from the assembler instructions? To link this code to correct fixed addresses? To get correct binary sizes? Problems with mirroring 0xF0000 and 0xFFFF0000? A few years ago I made a BIOS replacement for a SC520 CPU (486). Same way: Small real mode code, switching to PM immediately, setup cache as RAM and all the rest was done in C. In this project the linker was the key to get simple and working code.
With my GeodeGX1 systems I cannot use the mtrr registers to get some memory from the cache. To replace it a complete new file would be required. Maybe it would be better to support different methods how to get CAR and link them on demand?
The overhead of the reset vector and switching to protected mode before you enable CAR is 17 instructions (roughly). While you could factor that out, it is at the border between moving the complexity from one side (1 big file) to the other (composing several files and watching the code flow) and the philosophic unseemliness of having to duplicate 17 instructions per cpu type.
IMHO its not a question of "small code, no matter if duplicated". Its a matter of code quality: Its open source. Such current code I saw in many other closed source projects (a colleague calls it "Industrial Code Quality"). I believe we could make it better.
I don't really like the way it is done at the moment, working around weird bugs instead of fixing them, and I do quite some ironing out of the weird hacks in "lar".
No chance to fix it upstream? Thats our way: Don't patch every new release, send the patches upstream.
We're not a toolchain project, so we probably have to live with it ;)
Would it help, if we do our work with one or more reference toolchain(s)? GCC3.x, GCC4.x and so on? (*real* cross toolchains).
Juergen
* Juergen Beisert juergen127@kreuzholzen.de [070519 10:43]:
What do you mean with "old toolchains"? How old? I made some local changes to support my Geode GX1 and I would try it also with older toolchains (currently I'm working with a 4.1.2 cross toolchain).
Some current red hat eh fedore versions I think. No idea. Never had the issue.
So we changed it. Now it is exactly as fragile, but it is one fragile mess, not three of them.
My question is: What is fragile in this code? To get the correct opcodes from the assembler instructions? To link this code to correct fixed addresses? To get correct binary sizes? Problems with mirroring 0xF0000 and 0xFFFF0000?
Mostly to mix 32bit and 16bit code and still get the offsets in the jumps right. Check and see how we do db 0xe9 and then add a fake offset manually. I hate that code.
The overhead of the reset vector and switching to protected mode before you enable CAR is 17 instructions (roughly). While you could factor that out, it is at the border between moving the complexity from one side (1 big file) to the other (composing several files and watching the code flow) and the philosophic unseemliness of having to duplicate 17 instructions per cpu type.
IMHO its not a question of "small code, no matter if duplicated". Its a matter of code quality: Its open source.
Exactly. And code quality does not gain from splitting a single small task into 5 different files. We had that in v2, and nobody would understand it. stage0_xxx.S is something that never ever gets touched once it is written for a new CPU. How does code quality improve when you make three files out of it?
Such current code I saw in many other closed source projects (a colleague calls it "Industrial Code Quality"). I believe we could make it better.
It was better. We changed it back. But feel free to offer a patch or a terse description on improvement ideas.
LinuxBIOS is far better than "industrial code quality", if you ever had to read industrial bios code.
I don't really like the way it is done at the moment, working around weird bugs instead of fixing them, and I do quite some ironing out of the weird hacks in "lar".
No chance to fix it upstream? Thats our way: Don't patch every new release, send the patches upstream.
In binutils you mean?
We do, and they keep introducing new bugs, because the gnu toolchain is not made for bios development but for high level os stuff. We misuse it for a different purpose, and we have to pay the price.
We're not a toolchain project, so we probably have to live with it ;)
Would it help, if we do our work with one or more reference toolchain(s)? GCC3.x, GCC4.x and so on? (*real* cross toolchains).
Well yes and no. It works because then we have three code lines that noone ever touches can be made to look like sugar.
On the other hand it does not work because everybody would have to start building cross tool chains and we dont have enough people supporting them with their problems in this project.
I am not convinced that the gain is worth the effort.
Any ideas to change that are welcome!!!
Hi Stefan,
On Saturday 19 May 2007 11:08, Stefan Reinauer wrote:
- Juergen Beisert juergen127@kreuzholzen.de [070519 10:43]:
What do you mean with "old toolchains"? How old? I made some local changes to support my Geode GX1 and I would try it also with older toolchains (currently I'm working with a 4.1.2 cross toolchain).
Some current red hat eh fedore versions I think. No idea. Never had the issue.
So we changed it. Now it is exactly as fragile, but it is one fragile mess, not three of them.
My question is: What is fragile in this code? To get the correct opcodes from the assembler instructions? To link this code to correct fixed addresses? To get correct binary sizes? Problems with mirroring 0xF0000 and 0xFFFF0000?
Mostly to mix 32bit and 16bit code and still get the offsets in the jumps right. Check and see how we do db 0xe9 and then add a fake offset manually. I hate that code.
I know this problem.
The overhead of the reset vector and switching to protected mode before you enable CAR is 17 instructions (roughly). While you could factor that out, it is at the border between moving the complexity from one side (1 big file) to the other (composing several files and watching the code flow) and the philosophic unseemliness of having to duplicate 17 instructions per cpu type.
IMHO its not a question of "small code, no matter if duplicated". Its a matter of code quality: Its open source.
Exactly. And code quality does not gain from splitting a single small task into 5 different files. We had that in v2, and nobody would understand it. stage0_xxx.S is something that never ever gets touched once it is written for a new CPU.
And if you try to support a new CPU? Where to start? Copying one of the existing stage0_xxx.S and modifying until it works? ("Debug into existence")
How does code quality improve when you make three files out of it?
Assembler is always very specific. So one file for one dedicated function. The buildsystem is responsible to select and combine the right ones.
Such current code I saw in many other closed source projects (a colleague calls it "Industrial Code Quality"). I believe we could make it better.
It was better. We changed it back. But feel free to offer a patch or a terse description on improvement ideas.
LinuxBIOS is far better than "industrial code quality", if you ever had to read industrial bios code.
I did, yes :-)
We're not a toolchain project, so we probably have to live with it ;)
Would it help, if we do our work with one or more reference toolchain(s)? GCC3.x, GCC4.x and so on? (*real* cross toolchains).
Well yes and no. It works because then we have three code lines that noone ever touches can be made to look like sugar.
No! We will win reproducibility and reliability!
On the other hand it does not work because everybody would have to start building cross tool chains and we dont have enough people supporting them with their problems in this project.
The question is: Will this increase or decrease user's problems to work with LinuxBIOS? So can we have the focus on real hardware issues or have to waste time to worry about broken toolchains? Yes, the preparation needs more time, but after it we could start with the real job.
I am not convinced that the gain is worth the effort.
Any ideas to change that are welcome!!!
- reference toolchain(s) - documentation, the fragile a part is the more documentation it needs
I offer to work on both.
Juergen
* Juergen Beisert juergen127@kreuzholzen.de [070519 12:00]:
Exactly. And code quality does not gain from splitting a single small task into 5 different files. We had that in v2, and nobody would understand it. stage0_xxx.S is something that never ever gets touched once it is written for a new CPU.
And if you try to support a new CPU? Where to start? Copying one of the existing stage0_xxx.S and modifying until it works? ("Debug into existence")
take an existing one, remove the CAR code and add new CAR code. Nothing too wild.
How does code quality improve when you make three files out of it?
Assembler is always very specific. So one file for one dedicated function. The buildsystem is responsible to select and combine the right ones.
I think a single assembler file and no other need for assembler is pretty elegant. If there is a problem in the assembler code, you have exactly one location to check.
Doing the complexity in the build system instead of the single assembler file is possible. But where is the win?
One file for one dedicated function. Thats what stage0.S does. "get the machine to the state where you can execute gcc compiled code". Ie. this is the "extended arm" of the silicon.
I am absolutely on your side, but I ran out of reasons, so I am curious about what you think. I sat on the other side of the table and I am playing advocatus diaboli now.
Well yes and no. It works because then we have three code lines that noone ever touches can be made to look like sugar.
No! We will win reproducibility and reliability!
How is the current code not reproducable? How is the current code not reliable?
I had the code implemented that you suggest. It was teared out because the tenor is it looks nice but it is not reliable enough.
The question is: Will this increase or decrease user's problems to work with LinuxBIOS?
The code up to "enable CAR" is basically 3 assembler files and three linker scripts in LinuxBIOS v2. They got never changed since they were written. Can you make an example of your theoretically correct request for modularity and a more generic framework actually solves a problem that any developer (not even user) of LinuxBIOS will ever have?
So can we have the focus on real hardware issues or have to waste time to worry about broken toolchains? Yes, the preparation needs more time, but after it we could start with the real job.
We can do the real job, and we don't look at that one assembler file except when we port to a completely new CPU. Not a big deal. That problem is solved and we dont force any toolchain.
- reference toolchain(s)
- documentation, the fragile a part is the more documentation it needs
I offer to work on both.
Great. This would end the discussion. If it improves the situation we will of course be more than happy to use it!
Thanks for doing this.
Stefan
Juergen, what you are asking us to do is to revert to an old code model that did not work well, that caused great trouble as the gnu toolchain changed, and that people found confusing to read.
I agree with what Stefan has said. Furthermore, the stage0_i586.S file is fairly short, and almost no one should ever need to read it. That code should change very little. Most of it has been unchanged for 7 years. I find it most useful to have all the ugly assembly code in one file. And, even as simple as this file is, we had great trouble getting the GNU toolchain to build it properly. We hit several gld bugs, some of which have been "known bugs" for four years or more. We should not need a linker script for that simple file, but we do, in part due to these gld bugs. You can find our discussions on this dating back to Dec 2006 or so.
In V2, we have lots and lots of .S files, some with only one or two instructions and a segment name. These were stitched together via cpp and the linker. The system is incredibly flexible and can be configured in all sorts of ways. In practice, none of that flexibility is needed or used. I am sure that the design of this system followed some notion of good software engineering. It was also, for many people, completely incomprehensible.
The technique we are using for the *ONE* .S file in LinuxBIOS V3 is called "copy and convert". It works well in an industrial strength product, namely, the Plan 9 operating system, which is running in a router near you. As you find a new CPU, which needs a slightly different CAR design, you take the file, which has not changed in 7 years, and replace the CAR algorithm with your own, and create a new file name. It takes about 5 minutes. There are going to be very few files. I just went through this for the Geode LX and it took no time at all.
I appreciate your comments but I disagree completely with your ideas. Our experience has been that what you are proposing is a step in the wrong direction.
Sorry! :-)
thanks
ron
* Juergen Beisert juergen127@kreuzholzen.de [070519 10:43]:
IMHO its not a question of "small code, no matter if duplicated". Its a matter of code quality: Its open source. Such current code I saw in many other closed source projects (a colleague calls it "Industrial Code Quality"). I believe we could make it better.
The old code with a split off reset vector was around rev 62:
http://linuxbios.org/viewvc?view=rev&root=LinuxBIOSv3&revision=62