I put in a request for a quote for a "professional" ARMv8 assembly training class. Four 4-hour sessions delivered live online for $2500+.

For that kind of money I could fly myself to an ARM engineer's favorite watering hole and get private one-to-one knowledge transfer.

@djsundog Maybe I should offer professional Forth programming classes for $3000. It's valuable information to have, because the price says so!

Good money in training! More so than writing code. Gives the appearance of a scalable solution to the client, and comes out of a different budget. And you can charge per attendee, which is a different kind of scaling.

And as we know, every organisation needs Forth competence!

@vertigo @djsundog

Yeah, sorry, I realise you're in a bit of a corner. But it is worth considering what kinds of things bring in the income - they might not be just more of the same.

@vertigo @djsundog

@EdS @djsundog It's all I know how to do, though. I have no credentials for doing anything else.

@vertigo @EdS @djsundog

your kestrel project is more interesting than most lectures I've attended, and your general knowlege and opinions on programming and forth are valuable too. I'm jobless and near homeless right now, otherwise i'd gladly be your first customer. Nonetheless I'm sure I'm not the only one who'd shell out for it.

@drpeeper @EdS @djsundog Thanks for the kind words. However, the Kestrel project has one big advantage that companies do not offer me: freedom from hard deadlines.

To put it into context, I've been working on the Kestrel Project in some capacity since 2004.

@vertigo @EdS @djsundog
wouldn't really matter if it were 50 years old, it's a cool project that steps through the process of building your own system from scratch. just getting to the point you're at boggles most minds, and it'd make a great class as-is.

i'd kill for the opportunity to join a class where we built a kestrel clone, just up to the forth prompt.

@drpeeper @EdS @djsundog I'm open to suggestions and what the most consumable form this would take would be for people. I have always wanted to monetize side-projects related to Kestrel (e.g., printed user's and programmer's reference manuals, etc.).

Maybe bringing back my Over The Shoulder video tutorials? Hard to say, I'm learning all this stuff myself too.

OH, maybe I can make a vlog on Chisel HDL as I start off on Kestrel-3, and set up my Patreon again to support it. Thoughts?

@djsundog @drpeeper @EdS I would start with the new CPU, grow the circuit from there. But, first, I need to reinstall my workstation with Arch Linux and the the latest Chisel 3 package, Yosys, et. al., so I can get things working on the video.

@vertigo @djsundog @EdS
I agree with sundog, this is ALL useful stuff. Take us through all of it.

as for format, i'd personally like to see a materials list so I can plan out costs. offering live help might be nice, too. of course documentation and guides are important, but i'm also interested in the community aspect of a group of people building ip-capable machines.

@drpeeper @djsundog @EdS Yeah, community would be cool. "ip-capable" -- meaning TCP/IP?

@EdS @djsundog @drpeeper I only ask because the CPU I'm using doesn't offer protection facilities, so any operating system that runs on it will be single-address-space by definition. Using Linux or BSD will not be generally possible until the CPU is upgraded with protection facilities (e.g., page-based MMU and supervisor & user modes).

@vertigo @EdS @drpeeper that shouldn't preclude implementing a tcp/ip stack if one were so inclined though, right?

@djsundog @EdS @drpeeper Nope, but it'll not be as easy as just booting into Linux or BSD and typing ifconfig. You'll need to port a real-world OS, like AROS (AmigaOS open-source compatible OS), or Contiki (event-driven OS for embedded devices, but which has limited TCP/IP support). I haven't done any ports yet, and honestly, don't know how to even start such a project.

(Though if anyone knows how to start porting an OS, please let me know.)

@drpeeper @EdS @djsundog To be fair, I *intend* the CPU to have paging-MMU support and stuff, but it's a matter of me just sitting down and actually writing out the code for it. It must comply with established standards too, of course, which will always add complexity (committees and all that jazz).

Follow

Speaking of memory protection, I rather like the base-and-bounds model of protected regions - a whole lot simpler than an MMU!

As we know, Amiga worked pretty well without any relocation or protection, and the core of it was built on Tripos. As simple as possible, and no simpler...

cl.cam.ac.uk/~mr10/Cintpos.htm

@vertigo @drpeeper @djsundog

@EdS @vertigo @djsundog
I've long disliked the whole idea of virtual addressing anyways.

I remember the 💡 feeling when I got the load-time-relocation idea in the Amiga's executable format.

@drpeeper @vertigo @djsundog

@drpeeper @EdS @djsundog It's the only reasonable method for implementing very tight protections and virtual memory. Segments allow for virtual memory too, but at a much coarser granularity (entire objects, instead of just small chunks of them).

@EdS @drpeeper @djsundog Yes, RISC-V defines two base+bounds forms of protection which is definitely *very* easy to implement. However, it's not as general purpose as Intel-style segments, so for instance, one cannot share common binary images or common chunks of data between protection domains.

@EdS @drpeeper @djsundog Yes, AmigaOS runs fine in a single address space. I believe I have a method by which I can extend it to work in a page-protected environment as well, but I will basically need to fork AROS to be able to test my ideas. (Or, implement my own implementation of exec.library).

@EdS @vertigo @drpeeper @djsundog
you still need MMU for memory-mapped files, swapping pages to disk, etc.

OTOH, you can have protection separately from MMU - have all processes in a single MMU address space, and have per-process base-and-bounds protection on virtual addresses. Mill Architecture does it like this.

If you have an MMU, it's easier to do those things. But do you need to do them? The Amiga doesn't swap, nor did the Macintosh (I think.) And I would expect mapping files to memory is a relatively recent addition to the Unix-like family. (Maybe in SunOS?)

Of course there are lots of interesting questions about new CPUs for existing OS facilities. But I'm much more interesting in the minimum viable set of OS facilities, and appropriate CPUs for that.

@Wolf480pl @vertigo @drpeeper @djsundog

(BTW, I'd love to be able to express these thoughts without appearing argumentative! Or being one of those "well actually" people...)

@djsundog @drpeeper @vertigo @Wolf480pl

@EdS @Wolf480pl @drpeeper @djsundog The Amiga had virtual memory packages you could install to get both expanded memory space as well as improved reliability. It was a third-party add-on.

Macs evolved to swap as a feature of MacOS that you could turn on or off.

@EdS @Wolf480pl @drpeeper @djsundog "Do you need to do them?" is a fair question.

NOW? No. EVENTUALLY? Yes. :)

I don't think the Kestrel would be considered anything except an expensive toy if I didn't eventually support the user's *ability* to run Linux or BSD at some point in the future. It's already at a severe disadvantage compared to other platforms because it's FPGA-bound.

@vertigo @EdS @Wolf480pl @djsundog
the decision to make the machine linux/bsd capable is a good one, even if i'd be happy with a micro (was also thinking of building a propeller based system). after all, it's to be a pc, not a toy.

OTOH, I'm not convinced any of that complexity is necessary. I don't think the kernel aught to support filesystems or even block devices.

But I may have been reading too much chuck moore lately

@drpeeper @EdS @Wolf480pl @djsundog Well, you need to at least *bundle* a filesystem with the kernel (even if it doesn't run in kernel space) to bootstrap the rest of the system with. E.g., as with microkernels.

Forth is unique in that it's compact enough that reasonable amounts of code can be packed into 1KB chunks of raw block storage. That assumption wouldn't hold for other environments. :)

@drpeeper @EdS @Wolf480pl @djsundog That would be awfully nice. In the past, I've considered evolving my eForth port into a virtual machine manager of sorts, and kicking off eForth VMs in separate address spaces. (This is one area where base+bounds protection is more than sufficient to handle the job.)

@vertigo @EdS @Wolf480pl @djsundog
Me too, but first I need the school of kestrel to open registrations

@vertigo @drpeeper @EdS @djsundog
well, microkernels usually do have drivers, filesystems, etc. as userspace services, and they're all stored on the boot partition, next to the kernel, and the bootloader loads them all to memory.

@Wolf480pl @drpeeper @EdS @djsundog Yeah, I was responding to drpeeper's concerns specifically. :)

@EdS @vertigo @drpeeper @djsundog

I'm not interested in CPUs and OS facilities that will never have good performance.

Without mmap, the linker would have to copy executables (and shared libraries, if any) to RAM.
In order to share this memory with other processes executing the same binary, the linker would have to explicitely use shared memory.
Also, the OS wouldn't know the content in that memory is same as on disk, so it couldn't flush it to make space in RAM for other stuff.

@Wolf480pl @EdS @drpeeper @djsundog AmgiaOS is a prime counter-example to the distribution of shared libraries. It has libraries stuffed away in ROM as well as on-disk, and they do not replicate every time they're used.

Binaries will, of course, need to be replicated because AmigaOS takes a Unix-like approach to binaries. If it treated binaries as, say, Oberon does or even as Windows 2.0/3.0 does, then even this is no longer the case. But, you lose the ability to just have a main() function.

@Wolf480pl @EdS @drpeeper @djsundog Libraries are statically linked, relocated at load-time once, and linkage is provided through jump tables accessed relative to a base pointer.

@vertigo @EdS @drpeeper @djsundog so there is a system-wide service that loads libraries for other processes, and only loads them once?

@Wolf480pl @djsundog @drpeeper @EdS Nope; OpenLibrary() is akin to dlopen() in POSIX. (There's also a CloseLibrary() of course.) The difference between POSIX Shared Objects and AmigaOS libraries, though, is that the interface is known at compile time.

@EdS @drpeeper @djsundog @Wolf480pl So, for instance, if you wanted to call a single function Foo in library Bar, you might write in C:

BarBase = OpenLibrary("bar.library", 0);
if(!BarBase) { error("Can't open bar"); exit(1); }
Foo(); // Call the function
CloseLibrary(BarBase);

For this to work, you need a statically linked thunk of sorts, which is this in 68000 asm:

_Foo:
move.l _BarBase, a6
jmp _LVOFoo(a6)

@Wolf480pl @EdS @drpeeper @djsundog I'm honestly not familiar with what PLT is. Most dynamic linking features of ELF are black magic to me.

@djsundog @drpeeper @EdS @Wolf480pl At any rate, the point is this: near-term, it'd be nice to have an OS like AROS ported to the Kestrel. But, long term, it definitely needs a page-capable MMU so as to be able to run Linux. It would be a foolish move on my part to shut out an entire demographic of potential users or contributors just because of my own selfishness when it comes to what I'd like to run on my hardware.

@Wolf480pl @EdS @drpeeper @djsundog Yes, I'm ultimately building the Kestrel to meet my own needs. Once that's done, though, then I can be free to enhance the system to run more software for the greater open source community. I think that just makes the most sense.

@vertigo @EdS @drpeeper @djsundog

fprintf@plt:
jmp [got[fprintf_offset_in_got]]
push i_want_printf //prepare ags for dynamic linker
jmp dynamic_linker

got is Global Offset Table, basically a table of function pointers.
Initially, got[frpintf_offset_in_got] points to just after the first jmp in fprintf@plt.

Dynamic linker then puts address of fprintf in GOT, when fprintf@plt is first called.

@Wolf480pl @EdS @drpeeper @djsundog Ooh, neat!!

So when I call fprintf, it invokes fprintf@plt (I'm guessing @plt is just part of the symbol name) unconditionally.

The 1st time, the jmp is a glorified NOP, which then leads to code asking the DL to resolve the address of the library function. The DL uses the return address to compute the jmp instruction before it, and from that the address of fprintf_in_got. Given that, it patches it, then invokes the real fprintf.

@djsundog @drpeeper @EdS @Wolf480pl The 2nd time around, the jmp in fprintf@plt just branches directly to the implementation.

Is that a correct understanding?

@Wolf480pl @djsundog @drpeeper @EdS OK, so in that case, the static thunks are like a pre-resolved version of the PLT then.

@Wolf480pl @djsundog @drpeeper @EdS It is less convenient, perhaps, than shared objects to create a library; but it is at least automatable fairly trivially at build-time. But, at run-time, the benefits are the same, even despite lack of mmapping.

@Wolf480pl @EdS @drpeeper @djsundog Yes. exec.library has a function OpenLibrary() for this purpose.

@Wolf480pl @EdS @drpeeper @djsundog I genuinely don't see the point. I watched those videos, and you can still use paging to both enforce protection domains as well as provide virtual memory. Mill is slick in a lot of ways, but this is one area where I think it's more complex than it needs to be.

@vertigo @djsundog @drpeeper @EdS @Wolf480pl
Doesn't use of a single address space save a lot of time on TLB flushes ? Generally speaking I'm favorable toward moving more of the logic to software rather than hardware, it's easier to make it open source and it's possible to update for better security/performance without buying new chips.

@cjd @Wolf480pl @EdS @drpeeper @djsundog Modern paging hardware embeds a process ID into the TLB structures so thant needless TLB flushes no longer happens on context switch. Only on x86 does this still happen, but even here, "PCID" was recently introduced to combat this from happening.

I mean, yes, you're right; but it's not nearly as big a problem today as it was some years ago.

@EdS @vertigo @drpeeper @djsundog
I find the MMU is sort of like the garbage collector for C code. If you have a proper GC (with memory relocation & pointer rewriting) then you don't have fragmentation so it's not so much needed.

Knowing the pointers so you can relocate things: use handles!

"The Mac lacked [an MMU], so we needed to relocate memory in software to minimize fragmentation as blocks got allocated and freed. The Lisa word processor team used a memory manager with relocatable blocks, accessing indirectly through "handles", so the blocks could be moved as necessary to reduce fragmentation. We decided to use it too, recoding from Pascal to assembly."
goo.gl/2N5pkw

@cjd @vertigo @drpeeper @djsundog

@EdS @vertigo @drpeeper @djsundog
Neat history. I didn't know the Motorola macs had no MMU. As opposed to using handles and bouncing memory accesses, wouldn't it be faster at runtime to make the compiler generate code which tracks the proliferation of pointers so that they can all be updated when a block is moved ? For C this could be difficult but in languages without raw pointers it should be pretty easy.

@cjd @djsundog @drpeeper @EdS I believe Mac's Pascal compiler had support for handles.

@EdS @cjd @drpeeper @djsundog Even MacOS switched to using the MMU as of System 6 (experimentally) and more thoroughly in System 7. It improved system stability to the point where multi-Finder was actually usable, especially in the face of untrusted code.

Also, the MMU opened up virtual memory for the first time, rendering Mac's hard limits on allocation irrelevant.

@cjd @djsundog @drpeeper @EdS This is true in the most perfect of worlds. However, AmigaOS / AROS use raw pointers.

Handles are just ptrs to ptrs. In C, use **h instead of *p. But, you need to have the extra system calls to "lock" and "unlock" a block of memory, or else you run the risk of having the system move your block out from underneath your code. This all combined makes the code terribly inefficient with visible hit against perf.

@EdS @drpeeper @djsundog @cjd I should further point out that *eventually* I want Kestrel to be able to run Linux or similarly protected OS. So eventually, I'll need an MMU anyway.

Sign in to participate in the conversation
Mastodon @ SDF

"I appreciate SDF but it's a general-purpose server and the name doesn't make it obvious that it's about art." - Eugen Rochko