If two OSes use strictly different sets of physical hardware directly, and different CPU cores, then they can run simultaneously on the same machine without a hypervisor. Think about it, if they share absolutely no resources other than bus bandwidth, they don't care about the other OS. Of course, whether this is possible or not and to what extent depends on the system design; some systems will only have one of a critical resource (e.g. interrupt controller) and that limits what you can do using this approach.

This is already a common-ish thing to do on embedded systems with Linux. You can tell Linux to only use a subset of the available CPU cores, and then run your own bare-metal code on the remaining ones. This can be useful to, say, perform hard real-time tasks that are not amenable to running under Linux. For all intents and purposes there, your code (which might as well count as an OS, as it is bare-metal code) and Linux are sharing one machine there.

Similarly, you'll find that many systems are designed with multiple CPU cores sharing memory for different tasks. For example, on the Wii and Wii U, the main CPU (that games run on) and the IOP (security/IO CPU) share RAM, but run entirely separate OSes and each accesses a subset of available hardware. The CPUs aren't even of the same architecture. On some phones, the mobile baseband processor and main processor are also on a shared bus, but also run completely separate OSes. Sometimes both OSes are even Linux! And even on regular PCs, you could argue that certain add-on hardware with a coprocessor that has bus/DMA access is, effectively, a slice of the machine running another OS - say, for example, you might think of your NVMe controller this way.

The job of a hypervisor is to virtualize the hardware indeed, but what I meant with that is virtualizing things other than the CPU (e.g. peripheral devices). At the bare minimum, a hypervisor has to virtualize the CPU, which in practice means it runs the guest at a privilege level lower than itself.

In real life, hypervisors can range from "almost nothing, really" to a full blown virtual machine (which is what we normally think of, e.g. Qemu/KVM, VMWare, etc.). SimpleVisor is closer to the first - it gives you a platform to do things to the guest OS, but it's missing a lot that would be required to, say, actually share the screen between two OSes.

I'm building a thin hypervisor for the Apple M1, for debugging and reverse engineering purposes - the ultimate goal is to run macOS on it, so we can learn how it uses the hardware and then write Linux drivers for it. The way virtualization on ARM works, you can turn on VM features progressively. In the beginning, all my hypervisor did was execute the guest at EL1 (guest OS level), instead of EL2 (hypervisor level). There was literally nothing other than a few instructions to switch to EL1 and jump to the guest code. It's still enough to boot my own loader and then load Linux as a guest, and I used it to test that we supported running Linux as a guest correctly (since there are a few subtleties in the interrupt handling there). Does that count as a "hypervisor"? Then I started adding features; I added proper exception handlers (so I can perform actions when the guest does certain things), enabled traps on certain guest operations like accessing certain CPU registers, eventually set up page tables and virtual memory, then added code that can trap and emulate peripheral devices (which also involves emulating a tiny subset of the ARM instruction set in software), and it's slowly getting debugging features (notably missing is the ability to interrupt the guest on manual request, that's coming ~next, as well as virtual serial port support so we can get debugging output over USB instead of needing a custom serial cable). It's still a minimal thing that can't run two OSes at once (there is no context switching) and only supports one CPU core, but it can virtualize some hardware and let me debug and inspect the guest OS. At what point did it become a "real" hypervisor? That's up to you :)