x86 wreckages (was Using the task register to switch betw...

All off topic discussions go here. Everything from the funny thing your cat did to your favorite tv shows. Non-programming computer questions are ok too.
Post Reply
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

x86 wreckages (was Using the task register to switch betw...

Post by PeterX »

Korona wrote:That's the first time I ever heard somebody call SWAPGS "handy". SWAPGS is the greatest wreckage in the entire x86_64 architecture. (The second place is probably taken by NMIs.)
You sure are more expert on that. But my personal "hall of crap" of x86 are:

Place 1.) having to enable high mem (A20) explicitely

And to some lesser degree, but still sucking:
Place 2.) using the keyboard (!) controller for enabling A20
Place 3.) using the 16 x factor for real mode segments

Greetings
Peter
nexos
Member
Member
Posts: 1078
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: x86 wreckages (was Using the task register to switch bet

Post by nexos »

PeterX wrote:Place 1.) having to enable high mem (A20) explicitely
Yes, it is a pain. But without it, back in the day, MS-DOS would have failed to work! When MS-DOS became obsolete, they couldn't change it, as apps that enabled A20 depended on it existence. Backwards compatibility can be a big pain. I am becoming more of an EFI fan for this...
PeterX wrote:Place 2.) using the keyboard (!) controller for enabling A20
Yes, strange. I agree with this.
PeterX wrote:Place 3.) using the 16 x factor for real mode segments
Not the real mode segmentation expert, could someone expound on this :D ?
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: x86 wreckages (was Using the task register to switch bet

Post by PeterX »

nexos wrote:
PeterX wrote:Place 3.) using the 16 x factor for real mode segments
Not the real mode segmentation expert, could someone expound on this :D ?
I mean the segments style where 1:0 means the same as 0:0x10.
Well, it has become so normal, that most people don't notice this anymore and maybe it's not that bad if you consider the 16bit limitation back then.
Octocontrabass
Member
Member
Posts: 5521
Joined: Mon Mar 25, 2013 7:01 pm

Re: x86 wreckages (was Using the task register to switch bet

Post by Octocontrabass »

PeterX wrote:having to enable high mem (A20) explicitely
That's not really an x86 issue. If anything, you should blame Microsoft for it. There are non-AT-compatible x86 computers without an A20 gate. (Including UEFI computers, since UEFI is not AT-compatible.)
PeterX wrote:using the keyboard (!) controller for enabling A20
That's not really an x86 issue either. Blame IBM for that one. There are non-AT-compatible x86 computers with an A20 gate, and they just use an I/O port access to control it. (But the only ones I know of were never popular outside of Japan.)
PeterX wrote:using the 16 x factor for real mode segments
I don't see what's so bad about this. Yes, it's confusing if you're used to 32-bit or 64-bit systems with big linear address spaces, but the 8086 is a 16-bit CPU. One way or another, you had to translate those 16-bit logical addresses to physical addresses with more than 16 bits. Intel just happened to choose a method that could double as an easy way to make position-independent code.
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: x86 wreckages (was Using the task register to switch bet

Post by sj95126 »

There's no shortage of things to gripe about with the x86 - we're still struggling with many of the compromises made in the late 1970s - but for me some of the worst of it can be blamed on the 80286. I really wish Intel had just dumped that project in the trash and focused on the 386. It's possible we never would have become so buried in GDTs, LDTs, and other tricky concepts if the protections offered by paging had come first.

However, my biggest complaint is this: why the @^!#% did they have to preserve the format of a 16-bit descriptor and tack on extra fields, instead of reorganizing the layout? You can't say it was because of "compatibility" because only OS programmers need to touch descriptor tables, and they'd have to modify their code for 32-bit mode anyway. MAYBE you could argue that it made the logic gate pathways easier to reuse for both modes, in a time when there were real savings in avoiding adding a few hundred more transistors.

But there was NO excuse for 64-bit mode descriptors working this way. It's absurd to have to split your base (say, of an IDT gate) into three pieces when you should be able to set it with a single 64-bit MOV.

[revision: I know AMD created x64, not Intel - I wasn't suggesting that last part was Intel's fault, though it may have sounded like it because my train of consciousness was derailing)
nullplan
Member
Member
Posts: 1773
Joined: Wed Aug 30, 2017 8:24 am

Re: x86 wreckages (was Using the task register to switch bet

Post by nullplan »

sj95126 wrote:However, my biggest complaint is this: why the @^!#% did they have to preserve the format of a 16-bit descriptor and tack on extra fields, instead of reorganizing the layout? You can't say it was because of "compatibility" because only OS programmers need to touch descriptor tables, and they'd have to modify their code for 32-bit mode anyway. MAYBE you could argue that it made the logic gate pathways easier to reuse for both modes, in a time when there were real savings in avoiding adding a few hundred more transistors.
But at the time you fill in the GDT (and the processor reads it), it doesn't know what mode is going to be used. 32-bit mode is set by the D bit in the CS descriptor. Didn't they need to maintain 286 compatibility?

Actually I noticed that protected mode was really well thought through, and many of the problems plaguing us in 64-bit mode are simply not present. Segments can just be saved on stack and then overwritten, and it doesn't matter if a transition to kernel mode has been interrupted half way for this. Stacks get switched only on change of privilege level, or when getting an interrupt on a task gate. This means if you get an interrupt on a task gate, and then a normal interrupt, you just continue using the same stack. And if your task gate interrupt is hit twice before the first can return, that will fault (GPF or DF?) and not just clobber your stack.

Meanwhile in 64-bit mode, swapgs saves absolutely no state anywhere, so whenever you are entering the kernel, you have to check if you came from kernel mode already to know whether or not to swapgs again. Unless it is one of those interrupts that can occur at any time, like the NMI, where you must check if the swapgs has occurred or not. Changing CPL and running swapgs doesn't happen at the same time. And the thing does not stack at all. Speaking of stacks, thanks to the syscall instruction it is possible to be running in kernel mode without having a valid stack. I have absolutely no idea how to implement a syscall handler without using swapgs in an SMP context. But anyway, this means that for NMI, double fault, and machine check exception, you have to set up a separate stack using the IST. And if any of them happen a second time, the stack will be clobbered.

I mean, it is good that they tried to cut off old hair with 64-bit mode, but it appears they cut off a few good things along with it. And then had to re-enable earlier things again. Like the thing with the segment limits, which they bodged into the CPU again after having removed them. Turns out, some hypervisors were using those.
Carpe diem!
sj95126
Member
Member
Posts: 151
Joined: Tue Aug 11, 2020 12:14 pm

Re: x86 wreckages (was Using the task register to switch bet

Post by sj95126 »

nullplan wrote:But at the time you fill in the GDT (and the processor reads it), it doesn't know what mode is going to be used. 32-bit mode is set by the D bit in the CS descriptor. Didn't they need to maintain 286 compatibility?
Yeah, I know, backwards compatibility and all that. I was mostly venting about the need to be backwards-compatible in 64-bit mode where you can only use 64-bit descriptors anyway.

There's nothing necessarily wrong with backwards compatibility .. to a point. For example, it makes no sense whatsoever that the LMSW/SMSW instructions are still valid in 64-bit mode. Intel said to stop using those in 1986.
thewrongchristian
Member
Member
Posts: 425
Joined: Tue Apr 03, 2018 2:44 am

Re: x86 wreckages (was Using the task register to switch bet

Post by thewrongchristian »

PeterX wrote:
Korona wrote:That's the first time I ever heard somebody call SWAPGS "handy". SWAPGS is the greatest wreckage in the entire x86_64 architecture. (The second place is probably taken by NMIs.)
You sure are more expert on that. But my personal "hall of crap" of x86 are:

...
Place 3.) using the 16 x factor for real mode segments

Greetings
Peter
Oh, that's a piece of cake. I just want to know what they were smoking when they came up with the 286 protected mode model. I'd have just stuck a paging unit between the 1MB real mode address space and physical addresses.
PeterX
Member
Member
Posts: 590
Joined: Fri Nov 22, 2019 5:46 am

Re: x86 wreckages (was Using the task register to switch bet

Post by PeterX »

thewrongchristian wrote:I just want to know what they were smoking when they came up with the 286 protected mode model. I'd have just stuck a paging unit between the 1MB real mode address space and physical addresses.
Yeah, really true! But they were/are electronics specialists, not software specialists. And to their defense I must say: They invented hardware protection and this was all new. Today they have more knowledge about what's good for system developers. But you are right: They thought and designed in a really complicated way.

Greetings
Peter
thewrongchristian
Member
Member
Posts: 425
Joined: Tue Apr 03, 2018 2:44 am

Re: x86 wreckages (was Using the task register to switch bet

Post by thewrongchristian »

PeterX wrote:
thewrongchristian wrote:I just want to know what they were smoking when they came up with the 286 protected mode model. I'd have just stuck a paging unit between the 1MB real mode address space and physical addresses.
Yeah, really true! But they were/are electronic specialists, not software specialists. And to their defense I must say: They invented hardware protection and this was all new. Today they have more knowledge about what's good for system developers. But you are right: They thought and designed in a really complicated way.

Greetings
Peter
They were a long way from inventing the hardware protection techniques. Hardware protection had been mainstream in mainframes and minis since the 1960s, and many models of protection were well established by that point.

- Page based protection. Vax had already defined a purely paged based protection architecture, with a relatively simple user/supervisor model.
- IBM System/360, using MVS, had hardware protection capable of full virtual machine in 1974.
- Page based VM (and thus protection) goes back to at least the Atlas computer of 1962.
- Burroughs B5000 had segmentation based protection at about the same time.

But if you think the 286 is fscked up, read up on the i432, which was the 286's Itanium of the time, and thank our lucky stars that the 286 won out in the end.
linguofreak
Member
Member
Posts: 510
Joined: Wed Mar 09, 2011 3:55 am

Re: x86 wreckages (was Using the task register to switch bet

Post by linguofreak »

PeterX wrote:
nexos wrote:
PeterX wrote:Place 3.) using the 16 x factor for real mode segments
Not the real mode segmentation expert, could someone expound on this :D ?
I mean the segments style where 1:0 means the same as 0:0x10.
Well, it has become so normal, that most people don't notice this anymore and maybe it's not that bad if you consider the 16bit limitation back then.
It's best to think about it visually: Imagine you have a scroll of paper with marked lines hidden under a table, and a window in the table that you can look at part of the scroll through, big enough to show a large number of lines. Then you have a keypad and 7 segment display that you can use to enter a line number, after which the paper will be moved so that that line number selected will be at the top of the window.

Individual characters on the paper correspond to bytes in memory, lines correspond to 16 byte blocks (in DOS parlance often called "paragraphs"), the window corresponds to the 16-bit address space for one segment, the keypad and display correspond to the segment register, and the whole scroll is the 1 MiB real-mode address space.

So 1:0 can be thought of as "line 1, character 0". It gets a bit confusing if you refer to an address with a line number followed by a character number more than one line down the window ("line 1, character 2000"), but you can think of this as "line 1, then the 2000th character in the window". Also, for many DOS applications, memory requirements were low enough that you could just run with the base segment register value that DOS set up for the application and pretend you were on an unsegmented machine with 64k of memory.

-------------------------------------------------------------------------------------------------------

One change I would have made to the 8086, though, would be to add a user/kernel mode bit, and then make all instructions that wrote exact values to segment registers privileged. I then would have added ADDSEG and SUBSEG instructions that would be unprivileged, and the ability in kernel mode to set upper and lower limits for the values each segment register could have in user mode, with attempts to ADDSEG or SUBSEG above/below these limits trapping to kernel mode.

The effect this would have had would have been to allow the 8086 to act as a Turing machine, with each segment being a "head" on the "tape". Some portion of the virtual tape around each head would be stored in memory, and if a program tried to move a head beyond the region stored in memory for that head, there would be a segment limit exception, and the OS would swap some portion of the tape to disk, then swap in the region the head was moving into (or zero-initialize it if that part of the tape hadn't been touched before). This would have allowed applications to have an address space much larger than the address bus width of the processor, limited only by the capabilities of the OS and disk hardware.

But that's not so much "wreckage" as an interesting road not taken.
nullplan
Member
Member
Posts: 1773
Joined: Wed Aug 30, 2017 8:24 am

Re: x86 wreckages (was Using the task register to switch bet

Post by nullplan »

linguofreak wrote:One change I would have made to the 8086, though, would be to add a user/kernel mode bit, and then make all instructions that wrote exact values to segment registers privileged.
Well, that was specifically not the design goal for the 8086. The design goal was to update the 8080 to a 16-bit architecture and make sure that existing assembler code would be close to completely compatible. The 8086 assembler could be run in a mode where it recognized 8080 instructions and emitted the 8086 equivalents to them. The segmentation nonsense was added as a means of giving an 8080 program its own 64kB of address space without treading on any other program that may be loaded into memory already. The factor of 16 was chosen to be the smallest they could reach the 1MB with and still not loose a whole lot of space due to fragmentation. Any program can be loaded to any paragraph. And back when you counted every single byte of RAM, that alignment was already costly enough.

Privileged access to the machine was irrelevant as well, since the existing OS, CPM, had no way to take advantage of it. Secure access to machine resources is what you do on a mainframe, and the 8086 was no mainframe processor.
Carpe diem!
Octocontrabass
Member
Member
Posts: 5521
Joined: Mon Mar 25, 2013 7:01 pm

Re: x86 wreckages (was Using the task register to switch bet

Post by Octocontrabass »

nullplan wrote:
linguofreak wrote:One change I would have made to the 8086, though, would be to add a user/kernel mode bit, and then make all instructions that wrote exact values to segment registers privileged.
Well, that was specifically not the design goal for the 8086.
Maybe not the 8086 by itself, but Intel planned ahead well enough that at least one company was able to attach an external MMU to the 8086 to provide user/supervisor separation. (And paging!)
linguofreak
Member
Member
Posts: 510
Joined: Wed Mar 09, 2011 3:55 am

Re: x86 wreckages (was Using the task register to switch bet

Post by linguofreak »

nullplan wrote:
linguofreak wrote:One change I would have made to the 8086, though, would be to add a user/kernel mode bit, and then make all instructions that wrote exact values to segment registers privileged.
Well, that was specifically not the design goal for the 8086. The design goal was to update the 8080 to a 16-bit architecture and make sure that existing assembler code would be close to completely compatible.
I'm aware of this, it's just interesting how much could have been done with a fairly small and simple extension to the architecture. (And code written for the real architecture would run identically on the hypothetical architecture in kernel mode).
Privileged access to the machine was irrelevant as well, since the existing OS, CPM, had no way to take advantage of it. Secure access to machine resources is what you do on a mainframe, and the 8086 was no mainframe processor.
The point of the user/kernel mode in this hypothetical extension isn't even really security, it's simply allowing the OS to extend the address space arbitrarily with swap. The most minimal interpretation of what I described wouldn't deny I/O access to user mode, and you could even have the flag for user/kernel mode be user writable, you might call the modes "limited" and "free" instead of "user" and "kernel". The point is, code that wants to work with a arbitrarily large, swap-backed Turing tape would operate in limited/user mode, so that segment register increments/decrements beyond the portion of the tape in memory could be caught, whereupon the OS would bring in the appropriate section. Meanwhile, the OS, and any code that knew it could run comfortably within 1 MiB, would run in free/kernel mode. Such an extension to the 8086 architecture certainly *could* be designed to provide multitasking and security, but wouldn't need to be so designed.
Post Reply