Skip to content

Commit

Permalink
holy shit i am a god
Browse files Browse the repository at this point in the history
  • Loading branch information
tombl committed Jan 1, 2025
1 parent d06a7b8 commit 7049d9f
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 69 deletions.
4 changes: 1 addition & 3 deletions drivers/tty/tty_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1927,7 +1927,7 @@ static struct tty_driver *tty_lookup_driver(dev_t device, struct file *filp,
#endif
case MKDEV(TTYAUX_MAJOR, 1): {
struct tty_driver *console_driver = console_device(index);

pr_info("got console %p\n", console_driver);
if (console_driver) {
driver = tty_driver_kref_get(console_driver);
if (driver && filp) {
Expand Down Expand Up @@ -2042,8 +2042,6 @@ static struct tty_struct *tty_open_by_driver(dev_t device,
int index = -1;
int retval;

pr_info("tty_open_by_driver of %i %s\n", device, filp->f_path.dentry->d_iname);

mutex_lock(&tty_mutex);
driver = tty_lookup_driver(device, filp, &index);
if (IS_ERR(driver)) {
Expand Down
1 change: 1 addition & 0 deletions kernel/printk/printk.c
Original file line number Diff line number Diff line change
Expand Up @@ -3006,6 +3006,7 @@ struct tty_driver *console_device(int *index)

console_lock();
for_each_console(c) {
pr_info("console %s[%i] -> %p", c->name, c->index, c->device);
if (!c->device)
continue;
driver = c->device(c, index);
Expand Down
42 changes: 32 additions & 10 deletions tools/wasm/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,12 @@
});
</script>
<script type="module">
import { Machine } from "./dist/index.js";
import {
BlockDevice,
ConsoleDevice,
EntropyDevice,
Machine,
} from "./dist/index.js";

const term = new Terminal({
convertEol: true,
Expand All @@ -140,25 +145,42 @@
term.write("Error: not cross origin isolated\n");
}

const { cmdline = "no_hash_pointers", memory = 128 } = Object.fromEntries(
const { cmdline = "no_hash_pointers console=hvc0", memory = 128 } = Object.fromEntries(
new URLSearchParams(location.search)
);
document.querySelector("input[name=cmdline]").value = cmdline;
document.querySelector("input[name=memory]").value = memory;

const stdin = new ReadableStream({
start(controller) {
term.onData((data) => {
controller.enqueue(data);
});
},
});

const stdout = new WritableStream({
write(chunk) {
term.write(chunk);
},
});
const stdout2 = new WritableStream({
write(chunk) {
term.write(chunk);
},
});

const machine = new Machine({
cmdline: cmdline.replace(/\+/g, " "),
memoryMib: memory,
devices: [
new ConsoleDevice(stdin, stdout),
new EntropyDevice(),
new BlockDevice(new Uint8Array(8 * 1024 * 1024)),
],
});

machine.bootConsole.pipeTo(
new WritableStream({
write(chunk) {
term.write(chunk);
// return new Promise((r) => term.write(chunk, r));
},
})
);
machine.bootConsole.pipeTo(stdout2);

machine.on("halt", () => {
term.write("halting...");
Expand Down
16 changes: 13 additions & 3 deletions tools/wasm/run.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
#!/usr/bin/env -S deno run --allow-read
import { Machine } from "./dist/index.js";
import {
BlockDevice,
ConsoleDevice,
EntropyDevice,
Machine,
} from "./dist/index.js";
import { parseArgs } from "jsr:@std/cli@1/parse-args";
import { assert } from "./src/util.ts";

const args = parseArgs(Deno.args, {
string: ["cmdline"],
boolean: ["help"],
default: {
cmdline: "no_hash_pointers",
cmdline: "no_hash_pointers console=hvc0",
memory: 128,
cpus: navigator.hardwareConcurrency,
},
Expand All @@ -33,9 +38,14 @@ const machine = new Machine({
cmdline: args.cmdline,
memoryMib: args.memory,
cpus: args.cpus,
devices: [
new ConsoleDevice(Deno.stdin.readable, Deno.stdout.writable),
new EntropyDevice(),
new BlockDevice(new Uint8Array(8 * 1024 * 1024)),
],
});

machine.bootConsole.pipeTo(Deno.stdout.writable);
machine.bootConsole.pipeTo(Deno.stderr.writable, { preventClose: true });

machine.on("halt", () => {
console.log("halting...");
Expand Down
27 changes: 8 additions & 19 deletions tools/wasm/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@ import vmlinuxUrl from "./build/vmlinux.wasm";
import { type DeviceTreeNode, generate_devicetree } from "./devicetree.ts";
import init2 from "./init2.cpio";
import { assert, EventEmitter, get_script_path, unreachable } from "./util.ts";
import {
BlockDevice,
ConsoleDevice,
EntropyDevice,
virtio_imports,
VirtioDevice,
} from "./virtio.ts";
import { virtio_imports, VirtioDevice } from "./virtio.ts";
import { type Imports, type Instance, kernel_imports } from "./wasm.ts";
import type { InitMessage, WorkerMessage } from "./worker.ts";

export { BlockDevice, ConsoleDevice, EntropyDevice } from "./virtio.ts";

const worker_url = get_script_path(() => import("./worker.ts"), import.meta);

const vmlinux_response = fetch(new URL(vmlinuxUrl, import.meta.url));
Expand Down Expand Up @@ -45,21 +41,12 @@ export class Machine extends EventEmitter<{
cmdline?: string;
memoryMib?: number;
cpus?: number;
devices: VirtioDevice[];
}) {
super();
this.#boot_console = new TransformStream<Uint8Array, Uint8Array>();
this.#boot_console_writer = this.#boot_console.writable.getWriter();

this.#devices = [
new EntropyDevice(),
new ConsoleDevice(
new ReadableStream({
pull(controller) {
},
}),
),
// new BlockDevice(),
];
this.#devices = options.devices;

const PAGE_SIZE = 0x10000;
const BYTES_PER_MIB = 0x100000;
Expand Down Expand Up @@ -118,7 +105,9 @@ export class Machine extends EventEmitter<{
const vmlinux = await vmlinux_promise;

const boot_console_write = (message: ArrayBuffer) => {
this.#boot_console_writer.write(new Uint8Array(message));
this.#boot_console_writer.write(new Uint8Array(message)).catch(() => {
// Ignore errors if the console is closed
});
};
const boot_console_close = () => {
this.#boot_console_writer.close();
Expand Down
Binary file modified tools/wasm/src/init2.cpio
Binary file not shown.
84 changes: 50 additions & 34 deletions tools/wasm/src/virtio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,12 @@ export abstract class VirtioDevice<Config extends object = object> {
vqs: Virtqueue[] = [];
enable(vq: number, queue: Virtqueue) {
this.vqs[vq] = queue;
console.log("enable", vq, queue.size);
console.log("enable", this.constructor.name, vq, queue.size);
}
disable(vq: number) {
const queue = this.vqs[vq];
assert(queue);
console.log("disable", vq);
console.log("disable", this.constructor.name, vq);
}

abstract notify(vq: number): void;
Expand Down Expand Up @@ -236,12 +236,13 @@ export class BlockDevice extends VirtioDevice<BlockDeviceConfig> {
config_bytes = new Uint8Array(BlockDeviceConfig.size);
config = new BlockDeviceConfig(this.config_bytes);

storage = new Uint8Array(1024 * 1024);
#storage: Uint8Array;

constructor() {
constructor(storage: Uint8Array) {
super();
this.#storage = storage;
this.features |= BlockDeviceFeatures.FLUSH;
this.config.capacity = BigInt(this.storage.byteLength / 512);
this.config.capacity = BigInt(this.#storage.byteLength / 512);
}

override notify(vq: number) {
Expand Down Expand Up @@ -273,8 +274,8 @@ export class BlockDevice extends VirtioDevice<BlockDeviceConfig> {
assert(data.writable, "data must be writable when IN");
const start = Number(request.sector) * 512;
let end = start + data.array.byteLength;
if (end >= this.storage.length) end = this.storage.length - 1;
data.array.set(this.storage.subarray(start, end));
if (end >= this.#storage.length) end = this.#storage.length - 1;
data.array.set(this.#storage.subarray(start, end));
n = end - start;
status.array[0] = BlockDeviceStatus.OK;
break;
Expand All @@ -284,12 +285,6 @@ export class BlockDevice extends VirtioDevice<BlockDeviceConfig> {
status.array[0] = BlockDeviceStatus.UNSUPP;
}

console.log(
request.type,
request.sector,
status.array[0],
);

chain.release(n);
}
this.trigger_interrupt("vring");
Expand All @@ -302,40 +297,61 @@ export class ConsoleDevice extends VirtioDevice<EmptyStruct> {
config = new EmptyStruct(this.config_bytes);

#input: ReadableStream<Uint8Array>;
constructor(input: ReadableStream<Uint8Array>) {
#output: WritableStreamDefaultWriter<Uint8Array>;
constructor(
input: ReadableStream<Uint8Array>,
output: WritableStream<Uint8Array>,
) {
super();
this.#input = input;
this.#output = output.getWriter();
}

#writing: Promise<void> | null = null;
async #writer(queue: Virtqueue) {
const queueIter = queue[Symbol.iterator]();
for await (let chunk of this.#input) {
while (chunk.length > 0) {
const chain = queueIter.next().value;
if (!chain) {
console.warn("no more descriptors, dropping console input");
break;
}

override notify(vq: number) {
assert(vq === 0);
const [desc, trailing] = chain;
assert(desc && desc.writable, "receiver must be writable");
assert(!trailing, "too many descriptors");

const n = Math.min(chunk.length, desc.array.byteLength);
desc.array.set(chunk.subarray(0, n));
chunk = chunk.subarray(n);
chain.release(n);
}
}
}

override async notify(vq: number) {
const queue = this.vqs[vq];
assert(queue);
const queueIter = queue[Symbol.iterator]();

this.#writing ??= (async () => {
for await (let chunk of this.#input) {
while (chunk.length > 0) {
const chain = queueIter.next().value;
if (!chain) {
console.warn("no more descriptors, dropping console input");
break;
switch (vq) {
case 0:
this.#writing ??= this.#writer(queue);
break;
case 1:
for (const chain of queue) {
let n = 0;
for (const { array, writable } of chain) {
assert(!writable, "transmitter must be readable");
await this.#output.write(array);
n += array.byteLength;
}

const [desc, trailing] = chain;
assert(desc && desc.writable, "receiver must be writable");
assert(!trailing, "too many descriptors");

const n = Math.min(chunk.length, desc.array.byteLength);
desc.array.set(chunk.subarray(0, n));
chunk = chunk.subarray(n);
chain.release(n);
}
}
})();
break;
default:
console.error("ConsoleDevice: unknown vq", vq);
}
}
}

Expand Down

0 comments on commit 7049d9f

Please sign in to comment.