mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
RESET and SYSRQ is now trapped by a hypervisor
This commit is contained in:
@@ -37,7 +37,7 @@ function print_prompt_text() {
|
|||||||
con.addch(16);con.curs_right()
|
con.addch(16);con.curs_right()
|
||||||
con.color_pair(0,253)
|
con.color_pair(0,253)
|
||||||
print(" \\"+shell_pwd.join("\\").substring(1)+" ")
|
print(" \\"+shell_pwd.join("\\").substring(1)+" ")
|
||||||
if (errorlevel != 0) {
|
if (errorlevel != 0 && errorlevel != "undefined" && errorlevel != undefined) {
|
||||||
con.color_pair(166,253)
|
con.color_pair(166,253)
|
||||||
print("["+errorlevel+"] ")
|
print("["+errorlevel+"] ")
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ function print_prompt_text() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// con.color_pair(253,255)
|
// con.color_pair(253,255)
|
||||||
if (errorlevel != 0)
|
if (errorlevel != 0 && errorlevel != "undefined" && errorlevel != undefined)
|
||||||
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + " [" + errorlevel + "]" + PROMPT_TEXT)
|
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + " [" + errorlevel + "]" + PROMPT_TEXT)
|
||||||
else
|
else
|
||||||
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT)
|
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT)
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ hyve is a hypervisor for tsvm.
|
|||||||
3. hands the control over to the TVDOS until SysRq sequence is struck
|
3. hands the control over to the TVDOS until SysRq sequence is struck
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let context = parallel.spawnNewContext()
|
const bios = `
|
||||||
let bios = `
|
|
||||||
// probe bootable device
|
// probe bootable device
|
||||||
|
|
||||||
var _BIOS = {};
|
var _BIOS = {};
|
||||||
@@ -24,8 +23,6 @@ _BIOS.FIRST_BOOTABLE_PORT = [0,1]; // ah screw it
|
|||||||
|
|
||||||
Object.freeze(_BIOS);
|
Object.freeze(_BIOS);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// load a bootsector using 'LOADBOOT'
|
// load a bootsector using 'LOADBOOT'
|
||||||
let portNumber = 0;
|
let portNumber = 0;
|
||||||
let driveStatus = 0;
|
let driveStatus = 0;
|
||||||
@@ -54,17 +51,46 @@ else {
|
|||||||
printerrln("No bootable medium found.");
|
printerrln("No bootable medium found.");
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
let runner = parallel.attachProgram("TVDOS", context, bios)
|
|
||||||
parallel.launch(runner)
|
|
||||||
|
|
||||||
sys.sleep(1000);
|
let runner = undefined
|
||||||
|
|
||||||
|
function startNewInstance() {
|
||||||
|
runner = parallel.attachProgram("TVDOS", parallel.spawnNewContext(), bios)
|
||||||
|
serial.println("Starting new instance "+runner)
|
||||||
|
parallel.launch(runner)
|
||||||
|
sys.sleep(1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
// initial kickstart
|
||||||
|
startNewInstance()
|
||||||
|
|
||||||
while (parallel.isRunning(runner)) {
|
while (parallel.isRunning(runner)) {
|
||||||
graphics.plotPixel( // test fill the framebuffer to prove VM is shared
|
if (sys.peek(-49) >>> 7 == 1) {
|
||||||
(Math.random() * 560) | 0,
|
sys.poke(-49, 0)
|
||||||
(Math.random() * 448) | 0,
|
|
||||||
(Math.random() * 256) | 0
|
parallel.kill(runner)
|
||||||
)
|
|
||||||
|
graphics.clearText()
|
||||||
|
graphics.clearPixels(255)
|
||||||
|
|
||||||
|
startNewInstance()
|
||||||
|
}
|
||||||
|
else if (sys.peek(-49) >>> 6 == 1) {
|
||||||
|
sys.poke(-49, 0)
|
||||||
|
|
||||||
|
let threads = parallel.getThreadPool()
|
||||||
|
|
||||||
|
serial.println("======================")
|
||||||
|
for (let i = 0; i < threads.size; i++) {
|
||||||
|
serial.println(`Thread #${i+1}: ${threads[i]}`)
|
||||||
|
}
|
||||||
|
serial.println("======================")
|
||||||
|
|
||||||
|
sys.sleep(300)
|
||||||
|
}
|
||||||
sys.sleep(0)
|
sys.sleep(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,9 +74,10 @@ MMIO
|
|||||||
stores keys that are held down. Can accomodate 8-key rollover (in keyboard geeks' terms)
|
stores keys that are held down. Can accomodate 8-key rollover (in keyboard geeks' terms)
|
||||||
0x0 is written for the empty area; numbers are always sorted
|
0x0 is written for the empty area; numbers are always sorted
|
||||||
48..51 RO: System flags
|
48..51 RO: System flags
|
||||||
48: 0b r000 000t
|
48: 0b rq00 000t
|
||||||
t: STOP button (should raise SIGTERM)
|
t: STOP button (should raise SIGTERM)
|
||||||
r: RESET button (should reset the system)
|
r: RESET button (hypervisor should reset the system)
|
||||||
|
q: SysRq button (hypervisor should respond to it)
|
||||||
|
|
||||||
64..67 RO: User area memory size in bytes
|
64..67 RO: User area memory size in bytes
|
||||||
68 WO: Counter latch
|
68 WO: Counter latch
|
||||||
@@ -104,10 +105,12 @@ MMIO
|
|||||||
90 RO: BMS calculated battery percentage where 255 is 100%
|
90 RO: BMS calculated battery percentage where 255 is 100%
|
||||||
91 RO: BMS battery voltage multiplied by 10 (127 = "12.7 V")
|
91 RO: BMS battery voltage multiplied by 10 (127 = "12.7 V")
|
||||||
|
|
||||||
92..127 RW: Used by the hypervisor
|
|
||||||
|
|
||||||
1024..2047 RW: Reserved for integrated peripherals (e.g. built-in status display)
|
1024..2047 RW: Reserved for integrated peripherals (e.g. built-in status display)
|
||||||
|
|
||||||
|
2048..4075 RW: Used by the hypervisor
|
||||||
|
2048..2051 RW: Status flags
|
||||||
|
|
||||||
|
|
||||||
4076..4079 RW: 8-bit status code for the port
|
4076..4079 RW: 8-bit status code for the port
|
||||||
4080..4083 RO: 8-bit status code for connected device
|
4080..4083 RO: 8-bit status code for connected device
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
|
|||||||
38L -> keyboardInputRequested.toInt().toByte()
|
38L -> keyboardInputRequested.toInt().toByte()
|
||||||
39L -> rawInputFunctionLatched.toInt().toByte()
|
39L -> rawInputFunctionLatched.toInt().toByte()
|
||||||
in 40..47 -> keyEventBuffers[adi - 40]
|
in 40..47 -> keyEventBuffers[adi - 40]
|
||||||
48L -> ((vm.resetDown.toInt(7)) or (vm.stopDown.toInt())).toByte()
|
48L -> (vm.resetDown.toInt(7) or vm.sysrqDown.toInt(6) or vm.stopDown.toInt()).toByte()
|
||||||
|
|
||||||
in 64..67 -> vm.memsize.shr((adi - 64) * 8).toByte()
|
in 64..67 -> vm.memsize.shr((adi - 64) * 8).toByte()
|
||||||
68L -> (uptimeCounterLatched.toInt() or RTClatched.toInt(1)).toByte()
|
68L -> (uptimeCounterLatched.toInt() or RTClatched.toInt(1)).toByte()
|
||||||
@@ -116,7 +116,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
|
|||||||
89L -> ((acpiShutoff.toInt(7)) or (bmsIsBatteryOperated.toInt(3)) or (bmsHasBattery.toInt(1))
|
89L -> ((acpiShutoff.toInt(7)) or (bmsIsBatteryOperated.toInt(3)) or (bmsHasBattery.toInt(1))
|
||||||
or bmsIsCharging.toInt()).toByte()
|
or bmsIsCharging.toInt()).toByte()
|
||||||
|
|
||||||
in 92L..127L -> hyveArea[addr.toInt()]
|
in 2048L..4075L -> hyveArea[addr.toInt() - 2048]
|
||||||
|
|
||||||
in 1024..2047 -> peripheralFast[addr - 1024]
|
in 1024..2047 -> peripheralFast[addr - 1024]
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val hyveArea = ByteArray(128)
|
private val hyveArea = ByteArray(2048)
|
||||||
|
|
||||||
override fun mmio_write(addr: Long, byte: Byte) {
|
override fun mmio_write(addr: Long, byte: Byte) {
|
||||||
val adi = addr.toInt()
|
val adi = addr.toInt()
|
||||||
@@ -190,7 +190,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
|
|||||||
acpiShutoff = byte.and(-128).isNonZero()
|
acpiShutoff = byte.and(-128).isNonZero()
|
||||||
}
|
}
|
||||||
|
|
||||||
in 92L..127L -> hyveArea[addr.toInt()] = byte
|
in 2048L..4075L -> hyveArea[addr.toInt() - 2048] = byte
|
||||||
|
|
||||||
in 1024..2047 -> peripheralFast[addr - 1024] = byte
|
in 1024..2047 -> peripheralFast[addr - 1024] = byte
|
||||||
|
|
||||||
|
|||||||
@@ -285,11 +285,13 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
|
|||||||
private fun reboot(profileName: String) {
|
private fun reboot(profileName: String) {
|
||||||
val vm = currentlyLoadedProfiles[profileName]!!
|
val vm = currentlyLoadedProfiles[profileName]!!
|
||||||
|
|
||||||
vmRunners[vm.id]!!.close()
|
/*vmRunners[vm.id]!!.close()
|
||||||
coroutineJobs[vm.id]!!.interrupt()
|
coroutineJobs[vm.id]!!.interrupt()
|
||||||
|
|
||||||
vm.init()
|
vm.init()
|
||||||
initVMenv(vm, profileName)
|
initVMenv(vm, profileName)*/
|
||||||
|
|
||||||
|
// hypervisor will take over by monitoring MMIO addr 48
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateGame(delta: Float) {
|
private fun updateGame(delta: Float) {
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
|
|||||||
|
|
||||||
private lateinit var crtShader: ShaderProgram
|
private lateinit var crtShader: ShaderProgram
|
||||||
|
|
||||||
|
internal val whatToDoOnVmExceptionQueue = ArrayList<() -> Unit>()
|
||||||
|
|
||||||
fun loadShaderInline(frag0: String): ShaderProgram {
|
fun loadShaderInline(frag0: String): ShaderProgram {
|
||||||
// insert version code
|
// insert version code
|
||||||
val frag: String
|
val frag: String
|
||||||
@@ -156,7 +158,7 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
|
|||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
killVMenv()
|
whatToDoOnVmExceptionQueue.add { killVMenv() }
|
||||||
}
|
}
|
||||||
}, "VmRunner:${vm.id}")
|
}, "VmRunner:${vm.id}")
|
||||||
coroutineJob.start()
|
coroutineJob.start()
|
||||||
@@ -192,10 +194,12 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
|
|||||||
private var rebootRequested = false
|
private var rebootRequested = false
|
||||||
|
|
||||||
private fun reboot() {
|
private fun reboot() {
|
||||||
vmRunner.close()
|
/*vmRunner.close()
|
||||||
coroutineJob.interrupt()
|
coroutineJob.interrupt()
|
||||||
|
|
||||||
init()
|
init()*/
|
||||||
|
|
||||||
|
// hypervisor will take over by monitoring MMIO addr 48
|
||||||
}
|
}
|
||||||
|
|
||||||
private var updateAkku = 0.0
|
private var updateAkku = 0.0
|
||||||
@@ -226,6 +230,15 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
|
|||||||
renderGame(dt)
|
renderGame(dt)
|
||||||
|
|
||||||
vm.watchdogs.forEach { (_, watchdog) -> watchdog.update(dt) }
|
vm.watchdogs.forEach { (_, watchdog) -> watchdog.update(dt) }
|
||||||
|
|
||||||
|
|
||||||
|
val vmExceptionHandlers = whatToDoOnVmExceptionQueue.toList()
|
||||||
|
vmExceptionHandlers.forEach { it.invoke() }
|
||||||
|
synchronized(whatToDoOnVmExceptionQueue) {
|
||||||
|
vmExceptionHandlers.forEach {
|
||||||
|
whatToDoOnVmExceptionQueue.remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateGame(delta: Float) {
|
private fun updateGame(delta: Float) {
|
||||||
|
|||||||
Reference in New Issue
Block a user