Skip to content

Commit

Permalink
Virtio balloon
Browse files Browse the repository at this point in the history
  • Loading branch information
basicer committed Aug 27, 2024
1 parent 8d34247 commit 71018e4
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ CARGO_FLAGS=$(CARGO_FLAGS_SAFE) -C target-feature=+bulk-memory -C target-feature
CORE_FILES=const.js config.js io.js main.js lib.js buffer.js ide.js pci.js floppy.js \
memory.js dma.js pit.js vga.js ps2.js rtc.js uart.js \
acpi.js apic.js ioapic.js \
state.js ne2k.js sb16.js virtio.js virtio_console.js virtio_net.js \
state.js ne2k.js sb16.js virtio.js virtio_console.js virtio_net.js virtio_balloon.js \
bus.js log.js cpu.js debug.js \
elf.js kernel.js
LIB_FILES=9p.js filesystem.js jor1k.js marshall.js utf8.js
Expand Down
2 changes: 1 addition & 1 deletion debug.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"const.js config.js log.js lib.js buffer.js cpu.js debug.js " +
"io.js main.js ide.js pci.js floppy.js " +
"memory.js dma.js pit.js vga.js ps2.js rtc.js uart.js acpi.js apic.js ioapic.js sb16.js " +
"ne2k.js state.js virtio.js virtio_console.js virtio_net.js bus.js elf.js kernel.js";
"ne2k.js state.js virtio.js virtio_console.js virtio_net.js virtio_balloon.js bus.js elf.js kernel.js";

var BROWSER_FILES = "main.js screen.js keyboard.js mouse.js speaker.js serial.js network.js fake_network.js fetch_network.js starter.js worker_bus.js print_stats.js filestorage.js";
var LIB_FILES = "";
Expand Down
2 changes: 1 addition & 1 deletion nodejs-loader.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ let files = [
"src/virtio.js",
"src/virtio_console.js",
"src/virtio_net.js",
//"src/virtio_balloon.js",
"src/virtio_balloon.js",
"src/bus.js",

"src/debug.js",
Expand Down
3 changes: 3 additions & 0 deletions src/cpu.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ CPU.prototype.get_state = function()
state[81] = this.devices.uart3;
state[82] = this.devices.virtio_console;
state[83] = this.devices.virtio_net;
state[84] = this.devices.virtio_balloon;

return state;
};
Expand Down Expand Up @@ -551,6 +552,7 @@ CPU.prototype.set_state = function(state)
this.devices.uart3 && this.devices.uart3.set_state(state[81]);
this.devices.virtio_console && this.devices.virtio_console.set_state(state[82]);
this.devices.virtio_net && this.devices.virtio_net.set_state(state[83]);
this.devices.virtio_balloon && this.devices.virtio_balloon.set_state(state[84]);

this.fw_value = state[62];

Expand Down Expand Up @@ -983,6 +985,7 @@ CPU.prototype.init = function(settings, device_bus)
{
this.devices.virtio_console = new VirtioConsole(this, device_bus);
}
this.devices.virtio_balloon = new VirtioBalloon(this, device_bus);

if(settings.virtio_net)
{
Expand Down
207 changes: 207 additions & 0 deletions src/virtio_balloon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
"use strict";

// https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html#x1-2900003

const VIRTIO_BALLOON_F_MUST_TELL_HOST = 0;
const VIRTIO_BALLOON_F_STATS_VQ = 1;
const VIRTIO_BALLOON_F_DEFLATE_ON_OOM = 2;
const VIRTIO_BALLOON_F_FREE_PAGE_HINT = 3;

const STAT_NAMES = [
"SWAP_IN",
"SWAP_OUT",
"MAJFLT",
"MINFLT",
"MEMFREE",
"MEMTOT",
"AVAIL",
"CACHES",
"HTLB_PGALLOC",
"HTLB_PGFAIL",
];

/**
* @constructor
* @param {CPU} cpu
* @param {BusConnector} bus
*/
function VirtioBalloon(cpu, bus)
{
/** @const @type {BusConnector} */
this.bus = bus;
this.num_pages = 175000;
this.num_pages = 0;
this.actual = 0;
this.fp_cmd = 0;

const queues = [
{size_supported: 32, notify_offset: 0},
{size_supported: 32, notify_offset: 0},
{size_supported: 2, notify_offset: 1},
{size_supported: 64, notify_offset: 2},
];

//setInterval(() => this.GetStats(console.log.bind(console, "STATS")), 10000);

/** @type {VirtIO} */
this.virtio = new VirtIO(cpu,
{
name: "virtio-balloon",
pci_id: 0x0B << 3,
device_id: 0x1045,
subsystem_device_id: 5,
common:
{
initial_port: 0xD800,
queues: queues,
features:
[
VIRTIO_BALLOON_F_STATS_VQ,
VIRTIO_BALLOON_F_FREE_PAGE_HINT,
VIRTIO_F_VERSION_1,
],
on_driver_ok: () => {
dbg_log("Balloon setup", LOG_PCI);
},
},
notification:
{
initial_port: 0xD900,
single_handler: false,
handlers:
[
(queue_id) =>
{
const queue = this.virtio.queues[queue_id];
while(queue.has_request())
{
const bufchain = queue.pop_request();
const buffer = new Uint8Array(bufchain.length_readable);
bufchain.get_next_blob(buffer);
this.virtio.queues[queue_id].push_reply(bufchain);
let n = buffer.byteLength / 4;
this.actual += (queue_id === 0 ? n : -n);
console.log(queue_id === 0 ? "Inflate" : "Deflate", this.num_pages, this.actual, bufchain.read_buffers);
}
this.virtio.queues[queue_id].flush_replies();
},
(queue_id) =>
{
const queue = this.virtio.queues[queue_id];
if(queue.has_request())
{
const bufchain = queue.pop_request();
const buffer = new Uint8Array(bufchain.length_readable);
bufchain.get_next_blob(buffer);
let result = {};
for(let i = 0; i < bufchain.length_readable; i += 10) {
let [cat, value] = marshall.Unmarshall(["h", "d"], buffer, { offset : i });
result[STAT_NAMES[cat]] = value;
}
this.virtio.queues[queue_id].push_reply(bufchain);
if(this.stats_cb) this.stats_cb(result);
}
},
(queue_id) =>
{
const queue = this.virtio.queues[queue_id];
while(queue.has_request())
{
const bufchain = queue.pop_request();
if(bufchain.length_readable > 0) {
const buffer = new Uint8Array(bufchain.length_readable);
bufchain.get_next_blob(buffer);
let [cmd] = marshall.Unmarshall(["w"], buffer, { offset : 0 });
if(cmd === 0) {
if(this.fp_cmd > 1) this.fp_cmd++;
setTimeout(() => this.virtio.notify_config_changes(), 1000);
}
} else {
console.log("Free pages hinted", bufchain.read_buffers, bufchain.write_buffers);
bufchain.set_next_blob(new Uint8Array(bufchain.length_writable));
}
this.virtio.queues[queue_id].push_reply(bufchain);
}
this.virtio.queues[queue_id].flush_replies();
},
],
},
isr_status:
{
initial_port: 0xD700,
},
device_specific:
{
initial_port: 0xD600,
struct:
[
{
bytes: 4,
name: "num_pages",
read: () => this.num_pages,
write: data => { /* read only */ },
},
{
bytes: 4,
name: "actual",
read: () => {
console.log("Reported actual", this.actual);
return this.actual;
},
write: data => { /* read only */ },
},
{
bytes: 4,
name: "free_page_hint_cmd_id",
read: () => this.fp_cmd,
write: data => { /* read only */ },
}
]
},
});
}

VirtioBalloon.prototype.Grant = function() {
this.num_pages -= 75000;
console.log("Granting", this.num_pages);
this.virtio.notify_config_changes();
};

VirtioBalloon.prototype.Cleanup = function() {
this.fp_cmd = 2;
console.log("Receiving Free Pages");
this.virtio.notify_config_changes();
};


VirtioBalloon.prototype.get_state = function()
{
const state = [];
state[0] = this.virtio;
state[1] = this.num_pages;
state[2] = this.actual;
return state;
};

VirtioBalloon.prototype.set_state = function(state)
{
this.virtio.set_state(state[0]);
this.num_pages = state[1];
this.actual = state[2];
};

VirtioBalloon.prototype.GetStats = function(data)
{
this.stats_cb = data;
const queue = this.virtio.queues[2];
while(queue.has_request())
{
const bufchain = queue.pop_request();
this.virtio.queues[2].push_reply(bufchain);
}
this.virtio.queues[2].flush_replies();
};

VirtioBalloon.prototype.Reset = function() {

};

0 comments on commit 71018e4

Please sign in to comment.