6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 12:18 pm

All times are UTC




Post new topic Reply to topic  [ 53 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject:
PostPosted: Wed Jun 15, 2005 9:04 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
Jonas Cord wrote:
Is there no consensus as to whether this is possible or not?


There are no bugs with the 65816 and supporting restartable instructions. TMorita's statement comes from a confusion between normal interrupts like NMI and IRQ, and the ABORT input.

The ABORT input is different from IRQ/NMI in that it stops any future state updates inside the CPU, and causes the CPU to push the address of the currently executing instruction on the stack. Thus, when you execute the RTI instruction, the exact same instruction is restarted.

Note that the 65816 WILL update some CPU state for SOME instructions if you assert the ABORT input after the first cycle of an instruction. Note that the conditions under which this will occur are fully documented in the 65816 programmers reference, available on the WDC website. This usually won't be an issue, in most cases, as it only appears to affect a RMW-style instructions. But these are detectable in hardware up-front, as the 65816 will assert the ML (memory lock) signal for all RMW cycles. Therefore, an MMU can detect an early-attempt to write to memory by monitoring the ML signal as well as R/W, thus eliminating any possibility of inadvertent state updates.

So it is technologically possible to implement arbitrary memory protection and management logic on the 65816, and have it work "as expected."


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Jun 15, 2005 9:25 pm 
Offline

Joined: Tue Apr 12, 2005 3:24 am
Posts: 3
kc5tja,

Thank you for your informative response. That clears up the confusion for me, although I am a long way from being able to give any of these interesting ideas a try. One day...


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed Jun 15, 2005 9:46 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
Jonas Cord wrote:
kc5tja,

Thank you for your informative response. That clears up the confusion for me, although I am a long way from being able to give any of these interesting ideas a try. One day...


Not a problem. I am also interested in the possibility of adding support for hardware memory management to the 65816 as well. Not because it's particularly useful (heck, the Kestrel is hardly "useful" by any modern metric), but because the challenge is there. :)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Jan 12, 2007 1:04 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Quote:
Not a problem. I am also interested in the possibility of adding support for hardware memory management to the 65816 as well. Not because it's particularly useful (heck, the Kestrel is hardly "useful" by any modern metric), but because the challenge is there.


Hi,

just wanted to tell you that I have implemented hardware memory management (incl. stopping the CPU to swap memory on bus errors etc) for the 6502 :-)

Article:
http://www.6502.org/users/andre/icap/mp.html
Implementation, look at the CPU and AUXCPU boards:
http://www.6502.org/users/andre/csa/index.html

Have fun
André


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Jan 13, 2007 6:35 am 
Offline

Joined: Wed Oct 22, 2003 4:07 am
Posts: 51
Location: Norway
fachat wrote:
Hi,

just wanted to tell you that I have implemented hardware memory management (incl. stopping the CPU to swap memory on bus errors etc) for the 6502 :-)

Article:
http://www.6502.org/users/andre/icap/mp.html
Implementation, look at the CPU and AUXCPU boards:
http://www.6502.org/users/andre/csa/index.html

Have fun
André
If I understand you correctly, this works by stopping the CPU mid instruction, and using a second CPU to fix the error?

I looked over the all the available 6502 instruction (but not 65C02 instructions), and have come to the perhaps erroneous conclusions that it's possible to add a MMU with page faults, without an auxiliary CPU, with these conditions (and maybe some more I've forgotten to include):

-MMU makes sure illegal accesses always returns $00 (if it's a read), and causes a NMI
-Zero page and stack page can not be swapped out of memory
-Instructions can not straddle MMU page boundaries
-AND and JUMP INDIRECT instructions can only be issued when it is known that the operand will be in memory

Under those conditions it should be possible for the page fault handler to fix all errors. But I'm sure someone will object, I've probably missed something :)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jan 14, 2007 3:13 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Quote:
If I understand you correctly, this works by stopping the CPU mid instruction, and using a second CPU to fix the error?


Yes, exactly. Does not necessarily catch all conditions (e.g. when a page can not be swapped in), but works so far.

I plan to experiment with it in a branch of my GeckOS operating System.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jan 14, 2007 3:22 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
Quote:
I looked over the all the available 6502 instruction (but not 65C02 instructions), and have come to the perhaps erroneous conclusions that it's possible to add a MMU with page faults, without an auxiliary CPU, with these conditions (and maybe some more I've forgotten to include):

-MMU makes sure illegal accesses always returns $00 (if it's a read), and causes a NMI
-Zero page and stack page can not be swapped out of memory
-Instructions can not straddle MMU page boundaries
-AND and JUMP INDIRECT instructions can only be issued when it is known that the operand will be in memory

Under those conditions it should be possible for the page fault handler to fix all errors. But I'm sure someone will object, I've probably missed something


With this approach I see you can handle "no-execute" and "not mapped" errors in the program area. With the "instructions can not cross MMU page boundaries" you ensure that when crossing such a boundary, the first read from that page is an opcode fetch, which allows you to intercept it.

I do not see, however, how you would catch other bus access errors, especially in the data area. Any address included in an opcode (e.g. "LDA $e800") or indirect access ("LDA ($14),y") can point to a non-existing page. If you do not care about them, it's only half fun.

André


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jan 14, 2007 8:01 pm 
Offline

Joined: Wed Oct 22, 2003 4:07 am
Posts: 51
Location: Norway
fachat wrote:
With this approach I see you can handle "no-execute" and "not mapped" errors in the program area. With the "instructions can not cross MMU page boundaries" you ensure that when crossing such a boundary, the first read from that page is an opcode fetch, which allows you to intercept it.
Yeah, so if the page is not mapped the CPU will see a BRK instruction instead. The pagefault handler will map the page and continue executing from the start of the page
Quote:
I do not see, however, how you would catch other bus access errors, especially in the data area. Any address included in an opcode (e.g. "LDA $e800") or indirect access ("LDA ($14),y") can point to a non-existing page. If you do not care about them, it's only half fun.

André
I do care about them. If you do a LDA $e800 and page $e8 is not mapped, the accumulator get loaded with a zero, and then the pagefault handler will be called from the NMI, map in the page, and reissue the instruction, causing the correct data to be loaded. To find what the instruction pointer where before the NMI it should be possible to just scan through the current page from the start. This also works with OR and EOR, since (E)OR $00 does nothing, then the instruction will be reissued with the correct data. ADC and SBC can also be made to work, although its a tiny bit more complex (for the page fault handler). But AND is a problem, since AND $00 will clear the contest of A. Easiest solution is simply to disallow the opcodes for Absolute[,x/,y] and Indirect,(x/y), and make the program load the data into A or ZP before ANDing it.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sun Jan 14, 2007 8:03 pm 
Offline

Joined: Wed Oct 22, 2003 4:07 am
Posts: 51
Location: Norway
DP


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Feb 19, 2007 10:32 pm 
Offline

Joined: Sun Sep 15, 2002 10:42 pm
Posts: 214
Thowllly wrote:
I do care about them. If you do a LDA $e800 and page $e8 is not mapped, the accumulator get loaded with a zero, and then the pagefault handler will be called from the NMI, map in the page, and reissue the instruction, causing the correct data to be loaded.
...


Imagine:

Read page fault at $AB1
Previous three instruction bytes are $AE $B1 $0A
Memory starting at address $A contains: $B1 $0A
Y-register contains: $00

Was the previous instruction LDX $AB1, or was it LDA ($0A),Y?

Toshi


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon Feb 19, 2007 11:15 pm 
Offline

Joined: Wed Oct 22, 2003 4:07 am
Posts: 51
Location: Norway
TMorita wrote:
Thowllly wrote:
I do care about them. If you do a LDA $e800 and page $e8 is not mapped, the accumulator get loaded with a zero, and then the pagefault handler will be called from the NMI, map in the page, and reissue the instruction, causing the correct data to be loaded.
...


Imagine:

Read page fault at $AB1
Previous three instruction bytes are $AE $B1 $0A
Memory starting at address $A contains: $B1 $0A
Y-register contains: $00

Was the previous instruction LDX $AB1, or was it LDA ($0A),Y?

Toshi

I did imagine that, it was the first thing that immediatly came to mind. My solution was
Thowllly wrote:
To find what the instruction pointer where before the NMI it should be possible to just scan through the current page from the start.

The handler goes to $A00, checks the length of the instruction there, goes to the next instruction, finds the length of that instruction and so on until it reaches the last instruction before the NMI return address. This of course assumes there are no data or junk filled gaps between the instructions. I had that requirement in mind when I first thought about it, but it looks like I forgot to write it down...


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 20, 2007 1:09 am 
Offline

Joined: Sun Sep 15, 2002 10:42 pm
Posts: 214
Thowllly wrote:
The handler goes to $A00, checks the length of the instruction there, goes to the next instruction, finds the length of that instruction and so on until it reaches the last instruction before the NMI return address. This of course assumes there are no data or junk filled gaps between the instructions. I had that requirement in mind when I first thought about it, but it looks like I forgot to write it down...


Why do you assume that if you start parsing the instructions at $A00, you will be in sync with the instruction stream? I didn't specify where the instructions are. They could be anywhere in memory.

This could work if you applied additional restrictions of instructions not cross page boundaries, and separate memory areas for code and data. But at this point, I think you'd almost be better off using a virtual machine.

Toshi


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 20, 2007 6:00 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
Quote:
This of course assumes there are no data- or junk-filled gaps between the instructions.

I really know almost nothing about MMUs and I'm not very much "in tune" with this topic, but I will comment that in higher-level languages, it will keep going back and forth between link fields, headers, series of addresses of code fragments, and actual assembly-language code. It would be extremely limiting to say that a given page had to be solid machine-language instructions. Even with good use of macros to in essense raise the level of the language, assembly will often have data mixed in. Take for example the following piece of code in an assembly-language source:
Code:
        DISPLAY_IMM   "Press YES key to continue"
        WAIT_FOR_KEY  YESKEY

could display the message and then wait in a loop until the user presses the Yes/Continue key. The first line, "display immediate", indicates that the parameter is the actual string to display and not just an address. It might assemble
Code:
        JSR   DISP_QUOTE
        BYTE  25                          ; (25 is the string length)
        BYTE  "Press YES key to continue"

where the first line calls a subroutine, which uses the return address to pick up the next byte which tells how many bytes following make up the string that is to be displayed, gets the string, and advances the return address past the data to the next actual instruction. The WAIT_FOR_KEY line might assemble
Code:
ReScan: JSR  SCAN_KEYPAD
        CMP  #YESKEY
        BNE  ReScan

The two lines of code at the top make it very clear what you're doing and dramatically improve programmer efficiency, without giving up any runtime speed or memory, and without giving up any control. Unfortunately I think I have not been very successful in my "campaign" to get people here to take advantage of the macro capabilities of their assemblers though.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue Feb 20, 2007 11:54 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
To get the address of the instruction that caused an NMI, you must latch the state of the address bus when SYNC is asserted. That is the only reliable way to do it. Any other method will, eventually, fail you.

Then, when the NMI is generated, it needs to remember the state of those latches elsewhere (because the NMI handler will require instruction fetches, and therefore will overwrite what's in the latch the next time the CPU's SYNC is asserted). Thus, you need another set of latches.

This second set of latches is then read by the NMI handler to see what address the faulting instruction is at.


Top
 Profile  
Reply with quote  
PostPosted: Sun Jun 18, 2023 10:55 pm 
Offline

Joined: Thu Mar 31, 2022 6:40 am
Posts: 11
I'd like to note that, in order to easily protect the I/O area used by the MMU, it would
be trivial to arrange an ABORTB if the PID of the currently executing process is nonzero when access
is attempted to the controller side of the MMU.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 53 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: rwiker and 56 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: