Linked by Hadrien Grasland on Fri 30th Dec 2011 08:24 UTC
Hardware, Embedded Systems In the world of alternative OS development, portability across multiple architectures is a challenging goal. Sometimes, it may be intrinsically hard to come up with hardware abstractions that work well everywhere, but many times the core problem is one of missing information. Here, I aim at learning more about the way non-x86 architectures deal with CPU IO ports, and in particular how they prevent user-mode software from accessing them.
Order by: Score:
Memory mapped I/O.
by axilmar on Fri 30th Dec 2011 08:32 UTC
axilmar
Member since:
2006-03-20

From what I know, the 80x86 CPUs are the only family of CPUs to have a separate address space for I/O. The rest of the CPUs use memory mapped I/O i.e. hardware registers are mapped as memory cells, and the CPU uses the available load/store instructions to read/write the registers.

This has the advantage that the MMU can be used for controlling access to the I/O ports; no special circuitry is required.

Edited 2011-12-30 08:35 UTC

Reply Score: 4

RE: Memory mapped I/O.
by reduz on Fri 30th Dec 2011 13:22 UTC in reply to "Memory mapped I/O."
reduz Member since:
2006-02-25

Memory mapped IO is good. As the parent says it's simpler and more efficient and allows many neat tricks such as allowing other bus master devices to do stuff with hardware without the need of the CPU (ie: DMA for audio, video, etc).

Reply Score: 3

RE[2]: Memory mapped I/O.
by renox on Sat 31st Dec 2011 17:32 UTC in reply to "RE: Memory mapped I/O."
renox Member since:
2005-07-06

Memory mapped IO is good.


I wonder if it doesn't make virtualisation more difficult?
Explicit IO instructions seems much more easy to detect&handle for virtualisation.

Reply Score: 2

RE: Memory mapped I/O.
by zhulien on Sat 31st Dec 2011 02:59 UTC in reply to "Memory mapped I/O."
zhulien Member since:
2006-12-06

Z80 has separation, but it doesn't have restrictions of user mode and non-user mode.

Reply Score: 1

The headaches of Legacy Design.
by Snial on Fri 30th Dec 2011 09:54 UTC
Snial
Member since:
2011-12-30

On a non-x86 architecture it's easy and simple, you just map the memory addresses used for I/O out of user-space.

If we look at it a different way, I/O access is merely equivalent to an extra address bit, that is, you need an extra IO signal on a CPU, which could have been used to provide an extra address bit.

So, specific I/O instructions not only complicate work for the instruction set, compilers and device driver portability, but reduce memory space by a factor of two: and on the original 8-bit 8080 from which the x86 inherits its I/O model; the extra 64Kb would have been really valuable.

An I/O address space also doesn't really help even as an address space because virtually all practical computers from the 8-bit era onwards contained both I/O addressed hardware and memory-mapped hardware.

Video memory (actually an output device) was a common example. It was also true of the early 80s x86 PCs where addresses from 0xA0000 to 0xFFFFF were reserved for I/O, because the 1024 addresses provided by their (incompletely decoded) I/O slots weren't enough even then, 30 years ago.

So as you note, I/O portability is a problem for x86 PCs too since some I/O will be memory-mapped.

So why did Intel do this? Two reasons spring to mind: Firstly, the early Intel processors were really seen as embedded systems for controlling I/O, having a separate I/O signal reduced hardware (though this isn't convincing, you would still need additional decoding to handle more than 1 chip).

Secondly, and more probably, Intel were really memory chip producers and were new to processor design; employing people with no prior experience in computer architecture to design their early processors. Consequently, they simply copied I/O concepts from old minicomputers such as the pdp-8 and HP2100 without quite understanding why these machines had such features.

Hope this helps! (Julian Skidmore, designer of the DIY 8-bit computer FIGnition).

Reply Score: 6

blahbl4hblah Member since:
2011-05-29

Whoa! I just looked at the project that you mentioned...That is offing awesome!

Reply Score: 2

RE: The headaches of Legacy Design.
by Brendan on Fri 30th Dec 2011 12:33 UTC in reply to "The headaches of Legacy Design."
Brendan Member since:
2005-11-16

Hi,

On a non-x86 architecture it's easy and simple, you just map the memory addresses used for I/O out of user-space.


Just map the memory addresses used for I/O... and then spend weeks trying to figure out why something only works sometimes, just to find out you used the wrong explicit barrier/fence.

If an (out-of-order execution) CPU can't tell the difference between a memory mapped IO read/write and a normal RAM read/write, then it can be a nightmare for developers, tool-chains, etc.

If an (out-of-order execution) CPU has special instructions to access IO ports (and therefore can easily tell the difference between IO and RAM), then it can enforce strong ordering for these instructions and avoid the nightmare.

Of course if a CPU never supports out-of-order execution and/or enforces strong ordering for everything; then the problem mostly disappears (but so does a significant amount of potential performance).

- Brendan

Reply Score: 2

axilmar Member since:
2006-03-20

I don't think there is a big problem, because modern hardware provides all the means (disabling caches, memory barriers etc) to solve such issues.

Reply Score: 2

Vanders Member since:
2005-07-06

Just map the memory addresses used for I/O... and then spend weeks trying to figure out why something only works sometimes, just to find out you used the wrong explicit barrier/fence.


If you're writing an operating system then that's exactly the sort of thing you need to think about. You may as well have said "Just use I/O ports and then spend weeks trying to figure out why something doesn't work, just to find you were sending the wrong command byte."

Reply Score: 2

RE: The headaches of Legacy Design.
by viton on Sat 31st Dec 2011 04:53 UTC in reply to "The headaches of Legacy Design."
viton Member since:
2005-08-09

and on the original 8-bit 8080 from which the x86 inherits its I/O model; the extra 64Kb would have been really valuable.

IN/OUT is a special instructions with shorter encoding. external HW can be very simple like dedicated bit decoder in ZX-Spectrum. (8 bits -> 8 devices)

With 16bit register pairs, >64k is done via bank switching anyway.

Edited 2011-12-31 04:53 UTC

Reply Score: 2

Anachronda Member since:
2007-04-18

Consequently, they simply copied I/O concepts from old minicomputers such as the pdp-8 and HP2100 without quite understanding why these machines had such features.

Can't speak for the HP2100, but the PDP-8 didn't really have ports, per se. It had a single opcode, IOT, that caused I/O to happen. The remainder of the instruction was used to select a device and an operation. A device could do any combination of:

- Reading the value from the accumulator
- Clearing the accumulator
- ORing a value into the accumulator
- Skipping the next instruction

On later models like the PDP-8/e, the processor essentially halts and allows the I/O device access to the control points within the processor. An IOT on those systems can do pretty much anything the processor can.

Reply Score: 1

tylerdurden Member since:
2009-03-17

Hmmm.

You seem to have it backwards, port mapped I/O does not affect memory addressing since the CPU sees 2 different address spaces for all intents and purposes. that is one of the reasons why it was a common place design choice among early micros which had limited addressing capabilities.

Also since early micros from intel were mostly used as embedded controllers, it also made sense to segregate memory and I/O maps, since I/O devices tend to be much slower than memories. So they dealt with the latencies by adding complexity to the CPU, whereas memory mapped CPUs translated that complexity to the chipset.

Yes, under a modern 32+ bit address space with the levels of integration designers have access to (MMUs etc), either port or memory mapping I/O really has no much advantage over the other. But at the time, Intel actually knew what they were doing and port mapping made perfect sense.

Edited 2012-01-02 00:30 UTC

Reply Score: 2

Moto 68k
by Bill Shooter of Bul on Fri 30th Dec 2011 14:28 UTC
Bill Shooter of Bul
Member since:
2006-07-14

Its been years since I've been that close to bare metal, but when I was we were using memory mapped io on motorola 68k procs,

[Sorry for the double post]

Edited 2011-12-30 14:37 UTC

Reply Score: 2

RE: Moto 68k
by leech on Fri 30th Dec 2011 16:22 UTC in reply to " Moto 68k"
leech Member since:
2006-01-10

Isn't that one of the main reasons the Amiga rocked so hard, yet only had a 7.14mhz CPU (pretty sure that was the speed). Most things were handled through the bus, instead of the CPU having to handle all the I/O.

Reply Score: 2

RE[2]: Moto 68k
by ricegf on Fri 30th Dec 2011 17:06 UTC in reply to "RE: Moto 68k"
ricegf Member since:
2007-04-25

Exactly. The Amiga (and its spiritual predecessor, the beloved Atari 800) used custom chips to allow the processor to concentrate on processing rather than managing I/O.

Unfortunately, it also made upgrades to those architectures very expensive compared to commodity IBM PC designs.

There's no free lunch (to coin a phrase), but in the early years, the Atari / Amiga computers ran rings around the designs that finally conquered the market.

(An old codger reminisces - sorry 'bout that...)

Reply Score: 3

RE[3]: Moto 68k
by leech on Fri 30th Dec 2011 18:48 UTC in reply to "RE[2]: Moto 68k"
leech Member since:
2006-01-10

Ha, no worries. Loved my Atari 800XL. I still have it, but the last time I fired it up, the RF modulator was only sending black and white signals to the screen. Not sure if it was the cable, or something internal, but I did at one point drop it down my stairs...

Fortunately at one point in time I also managed to acquire an Atari 130XE.

Speaking of reminiscing.... at one point in time we had somehow managed to get strawberry jam on a floppy disk.

We washed it, and some of the stuff started working. Washed it two more times and all of it was working again. Those 5 1/4" floppies were hard to destroy!

Only at a much later date did I realize that Jay Miner created both the Atari 8-bits and the Amiga. Unfortunately, as most people I'm sure did, I upgraded to an Atari ST instead of the Amiga. Even though the C64 had it's share of bugs, the owners of those upgraded to the superior Amiga. The makers being opposite.

Now I'm rambling... cheers!

Reply Score: 3

RE[4]: Moto 68k
by zima on Fri 6th Jan 2012 23:59 UTC in reply to "RE[3]: Moto 68k"
zima Member since:
2005-07-06

At the risk of rekindling one long-forgotten Holy War ;) - 8bit Ataris and C64 were fairly comparable all around (the former also having its share of bugs) ...C64 somewhat better in some interesting areas (kinda discussed here, support chips and such), which made it the machine of the demoscene, one which essentially started it all. Seemingly much more long-lived, too.

Atari 16bit being what they were... overall it was probably better to be on the Commodore side of things throughout, unless maybe for MIDI (IIRC) of ST. At the least, my buddy who had both (8bit) machines, opted to get rid of small Atari much sooner than C64 (and BTW, most of the world didn't standardise on floppies in that generation, so any flaws of them on C64 were irrelevant; OTOH, later 8bit Atari models were legendarily... neurotic, when loading a game; probably also a case of different worlds, different "ecosystems" already http://www.osnews.com/thread?481346 )

Edited 2012-01-07 00:19 UTC

Reply Score: 2

RE[3]: Moto 68k
by BushLin on Sat 31st Dec 2011 13:24 UTC in reply to "RE[2]: Moto 68k"
BushLin Member since:
2011-01-26

I love looking back at the early Amiga days and wonder what might have been, wasn't going to reply but I'm really pedantic:

"to coin a phrase" means to invent a phrase, if it's then followed by a cliché I find it really jarring... enough to write a reply to someone I don't know, in the hope they don't do it again.

Reply Score: 1

RE[4]: Moto 68k
by ricegf on Sat 31st Dec 2011 23:46 UTC in reply to "RE[3]: Moto 68k"
ricegf Member since:
2007-04-25

When I list a cliché followed by "(to coin a phrase)", I'm making a mildly humorous reference to the fact that it is a cliché - not claiming that I actually invented the phrase! It's a little like saying "the Internet (as invented by Al Gore)..." - it's humor by farcical excess.

And yes, I'll do it again, as you're the first person in my 22 years of Internet posts to have admitted missing the intended humor. ;-)

Edited 2011-12-31 23:47 UTC

Reply Score: 2

RE[5]: Moto 68k
by siride on Sun 1st Jan 2012 03:24 UTC in reply to "RE[4]: Moto 68k"
siride Member since:
2006-01-02

It's not about humor, it's about the fact that you simply misused the phrase. "To coin a phrase" means to invent or come up with a new phrase. You were using a phrase, not inventing it.

Reply Score: 2

RE[6]: Moto 68k
by ricegf on Sun 1st Jan 2012 14:04 UTC in reply to "RE[5]: Moto 68k"
ricegf Member since:
2007-04-25

*whoosh*

Reply Score: 2

RE[7]: Moto 68k
by siride on Sun 1st Jan 2012 16:05 UTC in reply to "RE[6]: Moto 68k"
siride Member since:
2006-01-02

It's a pretty dumb joke.

Reply Score: 2

RE[3]: Moto 68k
by axilmar on Tue 3rd Jan 2012 11:55 UTC in reply to "RE[2]: Moto 68k"
axilmar Member since:
2006-03-20

The Atari series (XT/XL/ST) did not have the same mechanisms as the Amiga regarding DMA, and therefore things like playing a game on them while something loaded from floppy was not really possible to the same extent as the Amiga.

The Amiga was not more expensive than IBM compatibles. In fact, it was cheaper. An Amiga 600 would set you back for around 1000 dollars, whereas a PC with equivalent performance (think about the early days of 386 with VGA cards), would cost a lot more.

Reply Score: 2

RE[4]: Moto 68k
by zima on Fri 6th Jan 2012 23:55 UTC in reply to "RE[3]: Moto 68k"
zima Member since:
2005-07-06

Amiga 600 - hence heyday in 1993. An inexpensive machine, to be sure (much less expensive than you portray it; closer to what would be, after exchange, 200 dollars or so - of course without HDD and monitor, however a. they were hardly available anywhere in the first place b. what was almost always just a "gaming computer" didn't really need them) ...but essentially identical to Amiga 500, over half a decade old. As was 386, but even those didn't exactly stand still (I used some "surplus" late 386 in 97, it was quite nice with Win 3.11)

Which was more the point, I think - the tightly integrated architecture made the upgrades of the architecture (manufacturer side) expensive - engineering, implementation, it was almost either all or nothing (worse: with the dynamics of "installed base" very console-like ...but lacking appropriate in such case business model; Commodore essentially repeating US video game crash of the early 80s; coincidentally, the Amiga was supposed to be a console initially). Sure, that tight integration of hardware made Amiga nice & speedy for some time, but ultimately it largely limited its progress, arguably contributed to its demise.

Yes, there was 1200 - but not so affordable any more and... not really that much better, hardly compelling (most of the software people were interested in, ran happily on 500/600).

Edited 2012-01-07 00:12 UTC

Reply Score: 2

Moto 68k
by Bill Shooter of Bul on Fri 30th Dec 2011 14:36 UTC
Bill Shooter of Bul
Member since:
2006-07-14

{double post some how]

Edited 2011-12-30 14:37 UTC

Reply Score: 2

PIO versus MMIO
by Alfman on Fri 30th Dec 2011 16:21 UTC
Alfman
Member since:
2011-01-28

I actually found port I/O refreshingly easy to do in the DOS days. It could be done without regards to segment registers and caching modes.

As others have already mentioned, memory mapped IO might cause problems due to compiler optimisation quirks. But there are other subtle hardware differences too. For one, reading a port is explicit (such that reading changes a latch state), reading RAM may be inadvertent as the CPU reads in multiples of arbitrary cache-line sizes (possibly even if not cached?). Also, MMIO is affected by not only whether a page is cachable or not, but also by the MTRR.

For example, video memory is often set to write-combined to improve performance, but this could cause problems with other IO devices.

http://lwn.net/Articles/282250/


http://wiki.osdev.org/Paging

I'm not saying PIO is better, because it's not. However, it was simpler. I wish that PIO/MMIO could have been unified in a better way on the x86. Today PIO represents the legacyness of the platform. The consequence of this is that all CPUs designed to drive a PCI bus have to incorporate these legacy designs.

Reply Score: 2

IO on other platforms
by JLF65 on Fri 30th Dec 2011 16:29 UTC
JLF65
Member since:
2005-07-06

The PowerPC also has IO space. As part of the segment control, they can restrict IO space to supervisor-only access if needed. The PowerMac took advantage of this mechanism. As for memory mapped hardware (since PCI allows both hardware in IO space and in standard memory regions), the most common control mechanism is the MMU - all MMUs that I am familiar with allow for user/super access control. This is also how the x86/AMD64 controls access to memory mapped regions. It was how most older platforms controlled access to all the hardware (e.g., the old 68K Macs where ALL hardware was memory mapped).

Reply Score: 2

RE: IO on other platforms
by Alfman on Fri 30th Dec 2011 17:08 UTC in reply to "IO on other platforms"
Alfman Member since:
2011-01-28

JLF65,

"The PowerPC also has IO space. As part of the segment control, they can restrict IO space to supervisor-only access if needed. The PowerMac took advantage of this mechanism."

Yes, but I believe the original question posed by the article was how to allow user space micro-kernel drivers to access only those ports which they should have access to. Clearly you are correct that any (so called) ring 0 drivers can access the ports, but is it possible to allow drivers to access only a subset of ports?

I don't know the answer to this on non-x86 hardware.

Assuming the hardware doesn't provide a means to allow access to a subset of ports, then secure PIO would have to be delegated to a kernel helper function or some kind of secure user space stub. Arguably drivers don't *need* to be truly secure against malicious code, just secure enough to prevent most accidental crashes.

A kernel syscall for PIO is terribly slow and should be avoided. However a secure user space stub has it's own problems. The OS would need some sophisticated mechanism to comb through the driver's code to ensure it cannot generate unauthorised instructions (which is difficult, but VMWare uses the technique).

Additionally, even the secure stub function itself would be vulnerable to exploitation.

Consider:

if (port >= PX && port <= PY) {
outb(port, value);
}


The malicious driver could simply jump/call to the outb instruction directly to bypass the check.

In a managed language, this wouldn't be a problem, but it is with C/C++ which is what drivers are written in. It's one of the reasons I've been advocating using managed code in the OS for some time.

Reply Score: 2

RE[2]: IO on other platforms
by Alfman on Fri 30th Dec 2011 17:39 UTC in reply to "RE: IO on other platforms"
Alfman Member since:
2011-01-28

For the sake of completeness, another solution is just to give the drivers no port access and then just let the OS handle the resulting CPU faults and emulate the requested PIO. However it's not clear that this would perform any better than having an explicit PIO syscall.

The trouble with fault handlers is that the handler has to decode the instruction that caused the fault, which may or may not be a straitforward thing to do and it's architecture specific.


Edit: I'm probably overthinking the problem here. If platform doesn't permit fine grained control over port access, then just allow access to all ports and leave it at that. While it sucks that this goes against micro-kernel ideals, there's nothing wrong stating that it's a hardware limitation.

Edited 2011-12-30 17:44 UTC

Reply Score: 2

RE[2]: IO on other platforms
by TemporalBeing on Fri 30th Dec 2011 18:38 UTC in reply to "RE: IO on other platforms"
TemporalBeing Member since:
2007-08-22

In a managed language, this wouldn't be a problem, but it is with C/C++ which is what drivers are written in. It's one of the reasons I've been advocating using managed code in the OS for some time.


Managed code would still have a problem. Managed code does not solve security problems, just makes it harder for developers to do them by accident and harder to solve them when they do happen.

Reply Score: 3

RE[3]: IO on other platforms
by Alfman on Fri 30th Dec 2011 19:28 UTC in reply to "RE[2]: IO on other platforms"
Alfman Member since:
2011-01-28

TemporalBeing,

"Managed code would still have a problem. Managed code does not solve security problems, just makes it harder for developers to do them by accident and harder to solve them when they do happen."

It's still possible to write buggy code in a managed language, however managed languages do actually solve many security problems which have plagued C for years by making it impossible* to generate unauthorised/illegal instructions (such as jumping into the middle of a function as I illustrated earlier).

* to the extent that there aren't bugs in the VM.

In this instance, it would be possible for a VM to enforce port restrictions from a secure userspace stub without further kernel interactions.

Edited 2011-12-30 19:41 UTC

Reply Score: 2

RE[4]: IO on other platforms
by TemporalBeing on Fri 30th Dec 2011 20:06 UTC in reply to "RE[3]: IO on other platforms"
TemporalBeing Member since:
2007-08-22

TemporalBeing,

"Managed code would still have a problem. Managed code does not solve security problems, just makes it harder for developers to do them by accident and harder to solve them when they do happen."

It's still possible to write buggy code in a managed language, however managed languages do actually solve many security problems which have plagued C for years by making it impossible* to generate unauthorised/illegal instructions (such as jumping into the middle of a function as I illustrated earlier).

* to the extent that there aren't bugs in the VM.

In this instance, it would be possible for a VM to enforce port restrictions from a secure userspace stub without further kernel interactions.


Even with a pretty secure VM, you could still jump into a unauthorized/illegal instruction.

Managed languages do not magically solve those problems; they just make you do it on purpose as opposed to by accident.

That is, a newbie programmer won't likely do it; however, an experienced programmer who was setting out to do that kind of thing would be able to as they'd have a better understanding of the language they are using, the constraints, and the functionality to make it do so - but, only when they are purposely deciding to.

So, fully expect crackers to still abuse systems in fully managed - even TPM protected - code. That's their goal after all.

But those same constraints of the managed environment will also make it harder for even experienced programmers to protected from some of those things.

Reply Score: 2

RE[5]: IO on other platforms
by Alfman on Fri 30th Dec 2011 20:53 UTC in reply to "RE[4]: IO on other platforms"
Alfman Member since:
2011-01-28

TemporalBeing,



"Even with a pretty secure VM, you could still jump into a unauthorized/illegal instruction."

Can you provide any example where a bug-free VM produces unauthorized/illegal instructions?

"Managed languages do not magically solve those problems; they just make you do it on purpose as opposed to by accident."

I disagree with that. The concept of a VM is architecturally sound, even if an implementation of one may have faults.


"...an experienced programmer who was setting out to do that kind of thing would be able to as they'd have a better understanding of the language they are using, the constraints, and the functionality to make it do so - but, only when they are purposely deciding to."


One question for you: are you trying to imply that all VM code will always be buggy? Or are you implying that even a bug-free VM will inherently exploitable?


Take a simple managed language like Forth. All the external functions which can be called by the Forth program must be explicitly declared, so long as those functions are secure and don't allow the program to escape it's sandbox, then there will be no possibility for the program to call any other external functions.

Take another example, I can run a program inside of a QEMU VM. The code running under it will not have unauthorised access to the user-space which QEMU itself has access to. So again, the concept of QEMU is architecturally sound even if an implementation of it could have bugs.

Take a third example: the webbrowser has access to all user files, yet the programs running in javascript do not because the VM doesn't expose functionality to access those files. Short of bugs in the implementation, malicious javascript programs will not be able to access user files.

These are all examples of software VMs enforcing the access of external code. After all, the program running inside the VM is just a state machine. That state machine will be stuck inside the VM unless the VM provides it with handles to the outside world.


Of course, I can take nearly any secure VM and make it exploitable, for example by giving the program access to /proc/kcore, but that doesn't mean the VM MUST provide access to those exploits.

Reply Score: 2

RE[6]: IO on other platforms
by TemporalBeing on Fri 30th Dec 2011 22:08 UTC in reply to "RE[5]: IO on other platforms"
TemporalBeing Member since:
2007-08-22

""Even with a pretty secure VM, you could still jump into a unauthorized/illegal instruction."


Can you provide any example where a bug-free VM produces unauthorized/illegal instructions?
"

Well, show a VM that doesn't have bugs first.

""Managed languages do not magically solve those problems; they just make you do it on purpose as opposed to by accident."


I disagree with that. The concept of a VM is architecturally sound, even if an implementation of one may have faults.
"

The concept of a VM is sound yes, in theory.
However, in practice it is not quite as sound; this is mainly due, however, to the nature of programming languages.

However, you are getting off topic as the issue is not so much a VM as it is Managed Code. While Managed Code may use a VM, it does not necessarily need to do so; nor does a VM imply Managed Code.

""...an experienced programmer who was setting out to do that kind of thing would be able to as they'd have a better understanding of the language they are using, the constraints, and the functionality to make it do so - but, only when they are purposely deciding to."



One question for you: are you trying to imply that all VM code will always be buggy? Or are you implying that even a bug-free VM will inherently exploitable?
"

Again, you are off-topic. The issue is not a VM, but Managed Code itself; one does not necessarily imply the other.

A well written VM will not let you escape it - thus VMware, QEMU, Bochs, etc. allow programs to operate inside the virtual machine environment without having access to the host operating system. But they do not execute managed code - at least directly - they simply emulate what a CPU and the associated hardware does.

.NET is comprised of two things - a Virtual Machine and Managed Code. The Virtual Machine provides the operating environment much like QEMU does though for a different purpose - it does allow access to the host system because it has to in order to the the software do its job; it's more an OS Abstraction Layer than a VM.

The Managed Code portion of .NET is provided by C#, VB#, F#, and others. And, they comprise of programming structures like GOTO, which provides the functionality with the VM to get around exactly what the OP/GP talked about - skipping over a line (a check) to get to an otherwise protected line of code.


Take a simple managed language like Forth. All the external functions which can be called by the Forth program must be explicitly declared, so long as those functions are secure and don't allow the program to escape it's sandbox, then there will be no possibility for the program to call any other external functions.


Of your examples, this is the only one that actually touches the topic. Yet note that FORTH has a GOTO statement, which is all that is necessary to achieve the attack which the OP/GP was saying was impossible to achieve under Managed Code.

Take another example, I can run a program inside of a QEMU VM. The code running under it will not have unauthorised access to the user-space which QEMU itself has access to. So again, the concept of QEMU is architecturally sound even if an implementation of it could have bugs.


This is not quite on target (see above), but I'll bite anyway.

While yes, you won't be necessarily moving outside the virtual environment provided by QEMU, it still operates using the x86 assembly language (from ASM for 80086 to AMD64), which provides jmp,ljmp, far jmp, near jump, etc. - again, all that is necessary to thwart the attack that was being mentioned by the OP/GP.

Take a third example: the webbrowser has access to all user files, yet the programs running in javascript do not because the VM doesn't expose functionality to access those files. Short of bugs in the implementation, malicious javascript programs will not be able to access user files.


Again, ECMAScript/JavaScript has a GOTO statement in the language. Yes, you won't necesarily leave the VM that the web-browser provided, but you can make it do things that were unauthorized/unintended - for example, crashing another browser plugin module, or exploiting it to achieve a higher level of exploit (e.g. breaking out of the VM).

These are all examples of software VMs enforcing the access of external code. After all, the program running inside the VM is just a state machine. That state machine will be stuck inside the VM unless the VM provides it with handles to the outside world.


Please note the above - the topic was not about VMs but about Managed Code, even in the OS kernel.

A VM environment can certainly protect stuff running outside the VM from what is running inside it. However, that is neither here nor there when talking about Managed Code and enabling code to thwart a safety check put in by a programmer.

That is, if you have access to the source you can remove the code. If you don't, but you can put in something that is run in the same environment (e.g. sandbox, VM, etc.) then you can call into the other program by various means - whether a GOTO or Assembly jumps (the Assembly equivalent of GOTO) - and do things that were not otherwise intended by the original programmer.

VMs can only protect so far as in how the sandbox the applications.

Managed Code can only protect in so far as what the Programming Language does or does not provide in terms of functionality; but unmanaged code is pretty much the same. So when it comes to exploiting the two there really is no difference.

Of course, I can take nearly any secure VM and make it exploitable, for example by giving the program access to /proc/kcore, but that doesn't mean the VM MUST provide access to those exploits.


A VM must provide access in so far as what it is targeting to achieve. It is no different than an OS in that manner.

A hardware VM - e.g. QEMU, Bochs, VMware, etc - emulates the hardware and allows full operating system to operate. It need not provide any access to the actual hardware it is running on; though in practice and with the advent of the Virtual Machine instructions they do for performance reasons - namely making use of ring -1 and letting the guest OS thereby use ring 0-3 just like the host OS is doing.

An API VM - e.g. Java, .Net, SmallTalk, Python, etc - must allow access to the host OS so that they can achieve their desired functionality - writing programs in a given language that can do things desirable for the user - e.g. editing documents, browsing the web, etc. It is more of an API wrapper; it does provide some sand boxing of the running applications to protect two instances from each other but any plug-ins, etc. that the applications load are still within the memory confides of the application - in the same sandbox. The application is no more secure than a non-API VM language - e.g. C, C++, Pascal, Ada, etc. In fact, it may be less secure as the OS will use hardware functionality - pages, etc - to protect two applications from unnecessarily interacting; while the API VM cannot do so in itself - other than spawn another entire process to run the other applications and let the OS handle that side of it.

So again, the attack that was mentioned is still 100% possible under a Managed Code - it does not buy you anything in terms of protection by using Managed Code; it just changes the skill set required to make the exploit, and the likelihood that it will be done by accident.

Reply Score: 2

RE[7]: IO on other platforms
by Alfman on Fri 30th Dec 2011 22:51 UTC in reply to "RE[6]: IO on other platforms"
Alfman Member since:
2011-01-28

TemporalBeing,

"Well, show a VM that doesn't have bugs first."

It shouldn't matter, but for the sake of argument, take a look at the following turing machine implementation ;)

http://ironphoenix.org/tril/tm/


"Again, you are off-topic. The issue is not a VM, but Managed Code itself; one does not necessarily imply the other."

Why is it off topic? My assertion was that managed languages, through the use of a VM, can provide security that unmanaged languages cannot. I would like you to address this if you think I'm wrong. What makes me wrong? Are managed language VM's inherently insecure such that exploits are necessarily possible, or is it just difficult to prove the VM's don't have bugs?


"Please note the above - the topic was not about VMs but about Managed Code, even in the OS kernel."

I realise this, but my point was that some managed languages CAN provide additional security over unmanaged languages. Generally speaking managed languages do aim to enforce that code doesn't corrupt itself or execute illegal instructions - they do this by enforcing every state transition is legal and accounted for. I don't intend to get into a tussle over definitions, if you're uncomfortable with my use of the term "VM", then I'll simply retract that term and acknowledge that there are different ways (without VMs) to enforce managed code semantics whether in hardware or in software.



So getting back to the point...

"So again, the attack that was mentioned is still 100% possible under a Managed Code - it does not buy you anything in terms of protection by using Managed Code; it just changes the skill set required to make the exploit, and the likelihood that it will be done by accident."


If the managed language is sand boxed and does not provide a means to do port IO, then the program will effectively be unable to do port IO. Y/N?

Edited 2011-12-30 22:56 UTC

Reply Score: 2

RE[6]: IO on other platforms
by moondevil on Fri 30th Dec 2011 22:11 UTC in reply to "RE[5]: IO on other platforms"
moondevil Member since:
2005-07-08

Managed languages is a bad expression.

Managed language is just a term Microsoft created when they introduced .NET. Any so called managed language can also have compilers that target native code instead of bytecode generation.

Managed languages are better described as strongly typed languages.

It is true that it is also possible to exploit applications written in strongly typed languages, but they are harder to do.

If we restrict the exploits to VM environments, even if they have security managers for the bytecodes like the JVM and the CLR do, you might try to exploit the library. Many library methods are currently written in C/C++/Assembly, as such you can try to exploit the VM by passing invalid data to the library.

For example a corrupt image to the image handling library methods.

Reply Score: 2

RE[7]: IO on other platforms
by Alfman on Fri 30th Dec 2011 23:11 UTC in reply to "RE[6]: IO on other platforms"
Alfman Member since:
2011-01-28

moondevil,

"Managed languages is a bad expression."

Gosh, one of you has a problem with my use of "VM", another has a problem with my use of "managed language". I can't win, however I think you're both being overly pedantic, haha.

"If we restrict the exploits to VM environments, even if they have security managers for the bytecodes like the JVM and the CLR do, you might try to exploit the library. Many library methods are currently written in C/C++/Assembly, as such you can try to exploit the VM by passing invalid data to the library."

I totally agree, however it's still an implementation bug which can be fixed.

Obviously the kernel vs userspace separation can have exploits with buggy code in the kernel, but it doesn't invalidate the security concept of a kernel-userspace architecture in general. I think binding managed code to unmanaged libraries should be considered in the same light.

Reply Score: 2

RE[2]: IO on other platforms
by bartgrantham on Sat 31st Dec 2011 03:32 UTC in reply to "RE: IO on other platforms"
bartgrantham Member since:
2011-12-31

In a managed language, this wouldn't be a problem, but it is with C/C++ which is what drivers are written in. It's one of the reasons I've been advocating using managed code in the OS for some time.


I've heard this opinion expressed before, but I'm not sure I understand why anyone would feel this way.

What's the effective difference between a VM running in kernel space and a microkernel? Either you're trapping dangerous/unauthorized instructions in hardware or you're doing it in software. I don't really see much advantage to doing it in software except that bugs in that access layer can be updated when they are discovered.

Unless you're advocating something like what Open Firmware had where you could have drivers in bytecode that are cross-architecture compatible, but there's a performance reason why that was only used for bootstrapping and the OS shipped with CPU-specific drivers.

Reply Score: 1

"managed"
by daddio on Sat 31st Dec 2011 04:34 UTC in reply to "RE[2]: IO on other platforms"
daddio Member since:
2007-07-14

Why would anyone have a problem with the word "managed" as used to describe dotnet?

Because there was nothing new there that didn't already exist in other execution environments. They were not considered "managed".

It was PURE marketing.

It wasn't manged any more than java, or heck, interpretted languages like bash or BASIC, which run under the supervision of another process.

Reply Score: 1

RE[3]: IO on other platforms
by Alfman on Sat 31st Dec 2011 05:04 UTC in reply to "RE[2]: IO on other platforms"
Alfman Member since:
2011-01-28

bartgrantham,

"What's the effective difference between a VM running in kernel space and a microkernel? Either you're trapping dangerous/unauthorized instructions in hardware or you're doing it in software. I don't really see much advantage to doing it in software except that bugs in that access layer can be updated when they are discovered."


I'm happy you brought this up, although I'm pretty sure the author would consider this off topic.

There are some well known impediments with traditional micro-kernel designs, which are typically implemented using hardware userspace boundaries, as you observed. I'm sure I don't need to tell you, but I will elaborate anyways:

1. Kernel syscalls are slow, they often involve saving/loading various CPU register states and transferring data between userspace and kernel stacks.

2. IPC between drivers is usually much slower between micro-kernel drivers because data has to be copied from one address space to another. The equivalent operations in a macro-kernel involve simply passing around object pointers since macro-kernel drivers always share the same address space and drivers implicitly trust each other not to clobber the data of other drivers.


It's difficult to do anything to fix #1, we're basically at the whim of intel's engineers. The inefficiency can be measured in the difference in time between a normal function call and a syscall.

There are various things one might do to improve #2. One is to minimise the use of copied byte streams and design the IPC around shared memory instead. I'll let you ponder it, but none of the solutions are ideal.


A custom VM based micro kernel using a managed language would offer a potentially novel solution to both those problems.

Consider that in our managed language, a function can only access objects which it has a pointer/reference to. Even if other objects exist in the same address space, the managed language semantics prevent the function from touching objects for which no reference is available. We can take advantage of this fact by running two or more separate processes in the same address space (using one or more memory allocaters). Since the managed language guaranties that one process can never generate references to objects of the other process, the two processes can not corrupt each other. This achieves perfect process isolation without using hardware modes and without using any syscalls.

Now for IPC, we could designate specially typed references/pointers to guaranty the object pointed to is only referenced once by a process. Then these references/objects could be instantly transferred to the other processes running in the same address space using specialised constructs of the managed language. So transferring objects between drivers is as simple as passing a pointer in the macro-kernel approach.

So in a nutshell, you have microkernel drivers running in isolation under a kernel level VM without using hardware separation, and it doesn't have the overhead traditionally associated with userspace micro-kernels. You'd get all the other benefits of managed code as well, like those you mentioned.

Honestly there's nothing conventional about the micro-kernel approach I've illustrated. It's purely my own opinion and probably has little in common with the reasons others may have had to use VM based kernels.

Reply Score: 2

RE[4]: IO on other platforms
by Alfman on Sat 31st Dec 2011 06:46 UTC in reply to "RE[3]: IO on other platforms"
Alfman Member since:
2011-01-28

bartgrantham,

I wanted to list some other possible optimisations using managed code in a VM based micro-kernel:

3. A traditional micro-kernel with unmanaged code would typically need to validate that all parameters and data structures passed in are of the correct type and pointers are valid, which costs CPU cycles. However with managed code, the correctness of data structures and pointers might be inferred through strict types without checks.

4. It would take a hell of a good code optimiser to pull it off, but conceptually there's no reason the kernel VM couldn't automatically "inline" inter-driver function calls, such that there's *zero* function call overhead between microkernel drivers while keeping security semantics in place. After all, any steps taken by two functions, no matter what they do, could be done in one function instead.

Note: this might already happen with macro-kernel code using -O3, but this would be a very impressive speedup for a micro-kernel which typically requires a couple secure context switches for each IPC request between userspace drivers.

The main point to remember is that none of these microkernel optimisations are securely feasible using unmanaged code and hardware isolation.

Edited 2011-12-31 06:59 UTC

Reply Score: 2

RE[5]: IO on other platforms
by TemporalBeing on Tue 3rd Jan 2012 22:25 UTC in reply to "RE[4]: IO on other platforms"
TemporalBeing Member since:
2007-08-22

3. A traditional micro-kernel with unmanaged code would typically need to validate that all parameters and data structures passed in are of the correct type and pointers are valid, which costs CPU cycles. However with managed code, the correctness of data structures and pointers might be inferred through strict types without checks.


Both managed and unmanaged code do the same thing and require the same kinds of checks. Both offer strict-type checking when desired, and even with strict-type checking you can convert information from one type to another in manners to get around the compiler's strict type checking - even in manners that get around run-time strict type checking.

So the correctness of the data is not necessarily guaranteed even by simply using a Managed language.

Same goes for pointers - you can still end up with invalid pointers even in a managed language, and they can be just as damaging as in an unmanaged language.

Reply Score: 2

RE[6]: IO on other platforms
by Alfman on Tue 3rd Jan 2012 23:19 UTC in reply to "RE[5]: IO on other platforms"
Alfman Member since:
2011-01-28

TemporalBeing,

If you want help to understand something, then please ask it, I am still happy to answer genuine questions. However I am done responding to your doubts stated as negative assertions.

Reply Score: 2

RE[7]: IO on other platforms
by TemporalBeing on Wed 4th Jan 2012 14:46 UTC in reply to "RE[6]: IO on other platforms"
TemporalBeing Member since:
2007-08-22

TemporalBeing,

If you want help to understand something, then please ask it, I am still happy to answer genuine questions. However I am done responding to your doubts stated as negative assertions.


The fact that you don't understand the assertions or the difference between managed and unmanaged languages speaks for itself.

I have no doubts in the discussion; and am only correcting your incorrect view of what is available to you.

And, btw, if you really want to see what a Managed Language can/cannot do per an OS, look to Microsoft - only, they found they couldn't do it with a pure .NET language - e.g. C#, etc. - and had to create a special extension of C#. See here for more information:

http://singularity.codeplex.com/
http://en.wikipedia.org/wiki/Singularity_%28operating_system~*~...

As I and others have stated, it really offers no advantage over existing OS's, and rather has performance penalties as a result of the .NET side of things - a little more than a C++ or other OO-based languages, but similar to a Java-based OS, again for the same reasons.

Reply Score: 2

RE[4]: IO on other platforms
by TemporalBeing on Tue 3rd Jan 2012 22:21 UTC in reply to "RE[3]: IO on other platforms"
TemporalBeing Member since:
2007-08-22

Consider that in our managed language, a function can only access objects which it has a pointer/reference to. Even if other objects exist in the same address space, the managed language semantics prevent the function from touching objects for which no reference is available. We can take advantage of this fact by running two or more separate processes in the same address space (using one or more memory allocaters). Since the managed language guaranties that one process can never generate references to objects of the other process, the two processes can not corrupt each other. This achieves perfect process isolation without using hardware modes and without using any syscalls.


Except that managed languages do not make those guarantees.

Indeed, even if the language could make that guarantee, you could also use the language to locate the object without being strictly given access to it:

- create a reference to a memory segment to locate the object (e.g. searching memory to find it)
- decode another object that has a reference to it and steal a reference

In either case you were not explicitly granted a reference to the data but achieved it. These are both methods of cracking software, and both are also valid under managed languages.

So using a managed language buys you nothing in the end while costing a lot, in terms of performance

Reply Score: 2

RE[2]: IO on other platforms
by JLF65 on Sat 31st Dec 2011 17:52 UTC in reply to "RE: IO on other platforms"
JLF65 Member since:
2005-07-06

JLF65,

"The PowerPC also has IO space. As part of the segment control, they can restrict IO space to supervisor-only access if needed. The PowerMac took advantage of this mechanism."

Yes, but I believe the original question posed by the article was how to allow user space micro-kernel drivers to access only those ports which they should have access to. Clearly you are correct that any (so called) ring 0 drivers can access the ports, but is it possible to allow drivers to access only a subset of ports?

I don't know the answer to this on non-x86 hardware.

Assuming the hardware doesn't provide a means to allow access to a subset of ports, then secure PIO would have to be delegated to a kernel helper function or some kind of secure user space stub. Arguably drivers don't *need* to be truly secure against malicious code, just secure enough to prevent most accidental crashes.

A kernel syscall for PIO is terribly slow and should be avoided. However a secure user space stub has it's own problems. The OS would need some sophisticated mechanism to comb through the driver's code to ensure it cannot generate unauthorised instructions (which is difficult, but VMWare uses the technique).

Additionally, even the secure stub function itself would be vulnerable to exploitation.

Consider:

if (port >= PX && port


As mentioned, the PPC uses segment registers to restrict/allow access to IO. The way you allow users access to a subset of IO is simple - the user calls the kernel before doing any IO and gets assigned a segment register by the kernel to do what they want, if authorized. Segment registers cannot be set by the user since they are a system level part of the PPC architecture. IO segments control access to a variable amount of data, set in the segment itself. So the kernel has fine control over what the user may or may not access through the way it sets the segment register(s).

Any more detail on the subject is getting into OS design for PowerPC architecture, and I'm sure that actual code isn't the intention of the article, especially kernel level OS code. He just wanted to know the control mechanism.

Reply Score: 2

RE[3]: IO on other platforms
by Alfman on Sat 31st Dec 2011 18:42 UTC in reply to "RE[2]: IO on other platforms"
Alfman Member since:
2011-01-28

JLF65,

"As mentioned, the PPC uses segment registers to restrict/allow access to IO. The way you allow users access to a subset of IO is simple - the user calls the kernel before doing any IO and gets assigned a segment register by the kernel to do what they want,"

Thanks for clarifying. With my x86 background, the way it was written gave the impression that you were referring to a supervisor flag on the code segments which permitted all/nothing access to the IO ports (similar to ring# on x86).

So you are saying that segment registers can be used to grant port I/O access. I assume that PIO is done using against these segments using normal R/W instructions? If so, that seems better than the x86 approach.

Unfortunately I'm having trouble finding more information on the PPC using segments to do PIO. It looks like there are 16 segment registers available to do this with?

http://www.usenix.org/events/osdi99/full_papers/dougan/dougan_html/...

Edited 2011-12-31 18:51 UTC

Reply Score: 2

RE[4]: IO on other platforms
by JLF65 on Sun 1st Jan 2012 20:32 UTC in reply to "RE[3]: IO on other platforms"
JLF65 Member since:
2005-07-06

Thanks for clarifying. With my x86 background, the way it was written gave the impression that you were referring to a supervisor flag on the code segments which permitted all/nothing access to the IO ports (similar to ring# on x86).

So you are saying that segment registers can be used to grant port I/O access. I assume that PIO is done using against these segments using normal R/W instructions? If so, that seems better than the x86 approach.

Unfortunately I'm having trouble finding more information on the PPC using segments to do PIO. It looks like there are 16 segment registers available to do this with?

http://www.usenix.org/events/osdi99/full_papers/dougan/dougan_html/...


It's rather different than the x86. You want to read the Programming Environment Manual for the PPC. While there might be a web page that makes it easier to follow, I prefer the reference manuals. ;)

Note that 64 bit is completely different from 32 bit on the PowerPC. They don't have segment registers any more, but rather it's part of the MMU handling with tables of entries that control the same stuff as the segment regs... so it's like virtual segment registers with entries assigned by the OS.

32 bit: https://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B200...

64 bit: https://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/F7E732FF81...

Reply Score: 3

MMU
by matako on Fri 30th Dec 2011 17:09 UTC
matako
Member since:
2009-02-13

Usually whenever you have a CPU with a cache and a MMU, the MMU has the ability to define a page or a segment as non-cacheable, so that R/W operations hit the bus directly. A page can also be locked to physical addressing (no VM translation) and that is pretty much your memory-mapped I/O of the yesteryear.

Typically such facilities are only available in the kernel for hardware driver programming.

Edited 2011-12-30 17:24 UTC

Reply Score: 1

Considerations
by Brendan on Fri 30th Dec 2011 20:21 UTC
Brendan
Member since:
2005-11-16

Hi,

I thought I'd write some lists of things to consider. I split "IO" into 3 separate things - IO ports, memory mapped IO, and bus mastering/DMA.

For IO ports:
* what minimum granularity access control do you want (all or nothing, selected IO port ranges, or individual bits)
* what to do if you can't achieve the desired minimum granularity on some systems (emulate, or accept worse granularity)

For memory mapped IO only:
* If you can control caches, how does the driver set a memory mapped IO area's caching (e.g. "uncached" or "write combining" or "write through" or whatever the driver wants).

For memory mapped IO and bus mastering/DMA:
* what sort of fences/barriers do you need to support
* for systems where caches can't be controlled and systems where there is no cache coherency, how do you plan to handle cache coherency (e.g. explicit cache flushing that is ignored on targets that support cache coherency?)

For bus mastering/DMA only:
* are there IOMMUs that could be used to prevent a malicious driver from using bus mastering/DMA to access things it shouldn't be allowed to access
* if a device driver initiates a bus mastering/DMA transfer to RAM and then crashes before the transfer completes; can you isolate the RAM (so that it's not freed and re-allocated while the transfer is still in progress); and alternatively, can you forcibly terminate the transfer without a usable driver

For all of the above:
* can you safely give control of selected devices to arbitrary processes (e.g. so you can use a real network card from inside a virtual machine that's running as a process under your OS)

That's about all I can think of at the moment (but I'm sure I've missed something somewhere, as I mainly only deal with 80x86).

- Brendan

Reply Score: 2

The ps/2 port
by judgen on Sat 31st Dec 2011 11:44 UTC
judgen
Member since:
2006-07-12

This port might be the best ever invented for a keyboard. It standardises the input method. And the fact that it was the standard for so long (and still is for fast kvm switches) makes for a certain point. And WHY manufacturers still have a ps/2 port on most new motherboards is simple.
1:Why not,
2:Free (as in beer and no per chip/port cost like usb) so why not.
3: The best coders in the world still use the IBM-M Series or equal (no! lexmark with rubber thingies does not qualify) So why not?
4: It has direct hardware connection, USB does not and need a layer for usb support in the OS in a way that PS/2 does not. If you have one of those AMI BIOSES you know what i mean.
6: (I know it is the wrong number but i really wanted to make a point) BACKWARDS and FUTURE compatible. Ps/2 ports are still available to all shops for those using an apple or other retardedly maded laptop without ps/2, You can still use your ps/2 keyboard with computers from 1984 to this day without keyboard defucnt signals or dead keys (amiga fans know what i mean)

Also powering things from usb only have a theoretical voltage of 1.1V afaik PS/2 can power an external sound card,video out and a mug warmer on just one line of power.... I will not count that as an advantage, as that might also be its main flaw =D

Reply Score: 2

RE: The ps/2 port
by judgen on Sat 31st Dec 2011 12:00 UTC in reply to "The ps/2 port"
judgen Member since:
2006-07-12

And i forgot *silly me* The cpu cycles to do basic input is a LOT less with ps/2.

That might be negligible for most computers today, but waste is never a good idea. I prefer specialized ports ALL the way as long as the universal ones are available too. I hardly use them anyways but i bet most people use usb for more than installing Debian. So in other words, i am not most people,

Edited 2011-12-31 12:06 UTC

Reply Score: 2

RE[2]: The ps/2 port
by Doc Pain on Sun 1st Jan 2012 16:53 UTC in reply to "RE: The ps/2 port"
Doc Pain Member since:
2006-10-08

And i forgot *silly me* The cpu cycles to do basic input is a LOT less with ps/2.


Comparison: interrupt-driven vs. polling. :-)

Reply Score: 2

RE: The ps/2 port
by Doc Pain on Sun 1st Jan 2012 16:58 UTC in reply to "The ps/2 port"
Doc Pain Member since:
2006-10-08

Also powering things from usb only have a theoretical voltage of 1.1V afaik PS/2 can power an external sound card,video out and a mug warmer on just one line of power.... I will not count that as an advantage, as that might also be its main flaw =D


There is still hardware that "plugs into" the "keyboard input chain", such as barcode scanners and also card readers (as they are for example used in Germany for health insurance chips cards). Power is sometimes provided per PS/2 connector, control signals traditionally came per serial port, and "answers" were sent into the "keyboard input chain" and were immediately available to any program without any further device driver magic.

The PS/2 port still does not claim to be able of hot plugging. While I never had any issues disconnecting and reconnecting my IBN model M keyboard (often using its HIL plug), I've seen keyboard connectors dying several times - with other people, less lucky than me. :-)

Reply Score: 2

Memory mapped I/O and ports
by JPollard on Sat 31st Dec 2011 13:49 UTC
JPollard
Member since:
2011-12-31

IO ports go way back. The PDP1 (first computer under $100,000) had IO ports in 1960.

Memory mapped I/O (MMIO) was originally done by IBM, though it was cumbersome.

MMIO was used exclusively for I/O on the PDP11 (1970). Any address starting with 160000 and higher was reserved for I/O - the high order 3 bits would select/enable I/O activity. It was up to the interface as to how much support for memory actions (read/write/readlock/writelock) were supported. Some devices had only write support, others had various combinations. Most notably, the control status registers frequently had a "go" bit, which was always read as a 0.

This was carried out to the ultimate level with DEC VAX system - the high order 2 bits selected the system level - 00 - user, 01 - supervisor, 10 -interrupt, 11 device (as I recall).

MMIO is simpler to program, to debug, and faster, even on the X86, than using I/O instructions with ports.

The problem with IO instructions is three fold
1 - yet another instruction added to the CPU, and mandates CPU interaction with the peripheral - which can be HORRIBLY slow.
2 - yet another bus... or you make the memory bus perform double duty. A second bus is EXPENSIVE for a CPU to implement, so reusing the memory data bus is the usual result - with added complexity and expense on the bus (everything interfacing with it must implement a memory/IO select logic)
3 - another place to introduce bugs in CPU privilege separation (users cannot do I/O, for an example of the complexity just look at the X86 privilege bits...) MMIO is simpler as it can be controlled the same way memory is controlled - the MMU.

The advantage MMIO has is that any instruction can serve as an I/O instruction. System protection is just a pagefault away.

And normally you don't NEED the complexity of memory barriers other than the normal read/write locks supported by memory operation. This is required only for those system that have to reorder instruction sequences to achieve any kind throughput (an architectural problem, not a requirement).

The reason such locks are needed on the X86 is that the instructions are not executed by the processor - they are first translated into a stream of RISC instructions, where some get dropped as a "don't care" in the translation process. The memory barriers prevent the translator from making improper reordering operations.

Reply Score: 1

RE: Memory mapped I/O and ports
by Vanders on Sat 31st Dec 2011 15:17 UTC in reply to "Memory mapped I/O and ports"
Vanders Member since:
2005-07-06

The problem with IO instructions is three fold
1 - yet another instruction added to the CPU, and mandates CPU interaction with the peripheral - which can be HORRIBLY slow.


Not necessarily. S/360 I/O channels are certainly not slow. Although I guess it's arguable that programmable I/O channel controllers are not the same thing as I/O ports!

Edited 2011-12-31 15:18 UTC

Reply Score: 2

tylerdurden Member since:
2009-03-17

It can get into a semantic mess.

Programmable I/O Channel processors usually are not considered the same as I/O ports, because they don't execute processor instructions.

Whereas port I/O involves the processor executing I/O instructions explicitly.

Reply Score: 2

RE: Memory mapped I/O and ports
by Anachronda on Sat 31st Dec 2011 20:58 UTC in reply to "Memory mapped I/O and ports"
Anachronda Member since:
2007-04-18

This was carried out to the ultimate level with DEC VAX system - the high order 2 bits selected the system level - 00 - user, 01 - supervisor, 10 -interrupt, 11 device (as I recall).

You're actually mixing two different view of the VAX address space.

In a physical address, bit 29 typically selects I/O or memory. Bits 30 and 31 are typically used (at least in the microprocessor implementations) to encode the length of a transaction on the bus.

In a virtual address, bits 30 and 31 select the address space, where 00 is a user space growing up (i.e., code and data), 01 is a user space growing down (i.e., the user stack), 10 I'm fuzzy on, and 11 is system space. I/O typically winds up mapped into system space, although it's possible (with suitable privileges) to map regions of the other address spaces to I/O space.

Reply Score: 1

JPollard Member since:
2011-12-31

Not quite.

00 is user space. But the stack started at 01 and worked down (so the first usable byte is in 00).

DCL, RMS,and such lived in 01.

10 was where the kernel resided.

11 was reserved, but where all the physical devices lived. It mapped entire bus systems (UNIBUS,QBUS, BI...)

The system was mapped this way because that was the only way system calls could be made. The CMx (change mode to Kernel/whatever) instructions would not work in P0 space, system calls were an entry into P1/P2 address pages, and the first instruction was required to be a CMx instruction (then followed by a jump), otherwise an illegal access fault occurred.

As far as I recall (and I don't have my books handy) all physical I/O was defined by the MMU, and as such could use/map any physical bit of the bus for whatever it wanted. The CPU didn't interact with it (other than loading it via OS functions).

It was interesting with the boot code - it always emulated a PDP-11 during initial boot, with the default peripherals always mapped to 017xxxx (octal) address range. Didn't matter which bus was mapped (QBus/UNIBUS or the BI), that was where the peripherals were mapped by default. Once SYSBOOT was loaded, it (meaning the loaded boot program) would switch to native mode and initialize all the hardware and load the kernel.

Granted, I only worked on one VAX driver (a printer/plotter), but it's device address as used by the driver was starting with a 11 bit pattern.

Reply Score: 1

Anachronda Member since:
2007-04-18

Not quite. 00 is user space. But the stack started at 01 and worked down (so the first usable byte is in 00). DCL, RMS,and such lived in 01. 10 was where the kernel resided. 11 was reserved, but where all the physical devices lived.

Yeah, I knew I had botched 10 and 11 just after I posted it.

It mapped entire bus systems (UNIBUS,QBUS, BI...) The system was mapped this way because that was the only way system calls could be made. The CMx (change mode to Kernel/whatever) instructions would not work in P0 space, system calls were an entry into P1/P2 address pages, and the first instruction was required to be a CMx instruction (then followed by a jump), otherwise an illegal access fault occurred.

Hmm. I don't see those restrictions on the CHMx instructions in the VAX Architecture Reference Manual. The only restrictions I see are that CHMx cannot be executed while running on the interrupt stack and the new mode has to have enough privilege to access the old mode's stack.

It was interesting with the boot code - it always emulated a PDP-11 during initial boot, with the default peripherals always mapped to 017xxxx (octal) address range. Didn't matter which bus was mapped (QBus/UNIBUS or the BI), that was where the peripherals were mapped by default. Once SYSBOOT was loaded, it (meaning the loaded boot program) would switch to native mode and initialize all the hardware and load the kernel.

I'm curious about which machine you worked with. The big machines tended to have a captive PDP-11 (LSI-11 in the case of the /780, various Pro models in 8xxx machines). As I understand it, the PDP-11 was responsible for loading the microcode into the processor and the bootstrap into memory, then lighting off the VAX.

QBus machines tended to be built with processors that didn't support compatibility mode. At reset, they'd start running VAX code from ROM, which would go fetch the bootstrap.

I'm not sure how the /730 and /750 booted.

Reply Score: 1

RE: Memory mapped I/O and ports
by tylerdurden on Wed 4th Jan 2012 09:33 UTC in reply to "Memory mapped I/O and ports"
tylerdurden Member since:
2009-03-17

ugh, you're a bit confused as to why memory barriers are needed.

They are not a "x86 thing," although technically it should be an out-of-order thing really since any speculative RISC design also has to deal with the same problem.

Memory mapped I/O becomes tricky in speculative architectures due to the complex interaction between the load/store queues and the cache/memory controller. And even in in-order architectures memory barriers may be needed due to cache/memory controller/chipset interactions.

For normal (i.e non I/O) operations the specific order of a write is not crucial as long as it happens before another instruction needs that result executes. And the processor can guarantee that data dependencies are met, since it is the only one scheduling those instructions. However, once we're dealing with I/O instructions, we are now accessing the scheduling realm of the I/O device not just the processor's. So the assumptions from non I/O memory accesses do not apply in this case.

Edited 2012-01-04 09:34 UTC

Reply Score: 2