Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/c/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ export fn sdfgen_irq_ioapic_create(ioapic: u64, pin: u64, c_trigger: [*c]binding
log.err("failed to create IOAPIC IRQ at chip {}, pin {}, vector {}: invalid polarity '{}'", .{ ioapic, pin, vector, c_polarity.* });
allocator.destroy(irq);
return null;
}
},
};
options.polarity = polarity;
}
Expand Down Expand Up @@ -535,14 +535,16 @@ export fn sdfgen_channel_add(c_sdf: *align(8) anyopaque, c_ch: *align(8) anyopaq
sdf.addChannel(ch.*);
}

export fn sdfgen_sddf_timer(c_sdf: *align(8) anyopaque, c_device: ?*align(8) anyopaque, driver: *align(8) anyopaque) *anyopaque {
export fn sdfgen_sddf_timer(c_sdf: *align(8) anyopaque, c_device: ?*align(8) anyopaque, driver: *align(8) anyopaque, virt: *align(8) anyopaque) *anyopaque {
const sdf: *SystemDescription = @ptrCast(c_sdf);
const timer = allocator.create(sddf.Timer) catch @panic("OOM");
timer.* = sddf.Timer.init(
allocator,
sdf,
if (c_device) |raw| @ptrCast(raw) else null,
@ptrCast(driver)
@ptrCast(driver),
@ptrCast(virt),
.{},
);

return timer;
Expand Down Expand Up @@ -596,7 +598,7 @@ export fn sdfgen_sddf_serial(c_sdf: *align(8) anyopaque, c_device: ?*align(8) an
}
const serial = allocator.create(sddf.Serial) catch @panic("OOM");
serial.* = sddf.Serial.init(allocator, sdf, if (c_device) |raw| @ptrCast(raw) else null, @ptrCast(driver), @ptrCast(virt_tx), options) catch |e| {
log.err("failed to initialiase serial system: {any}", .{ e });
log.err("failed to initialiase serial system: {any}", .{e});
allocator.destroy(serial);
return null;
};
Expand Down Expand Up @@ -726,12 +728,11 @@ export fn sdfgen_sddf_gpio_serialise_config(system: *align(8) anyopaque, output_
return true;
}


export fn sdfgen_sddf_blk(c_sdf: *align(8) anyopaque, c_device: ?*align(8) anyopaque, driver: *align(8) anyopaque, virt: *align(8) anyopaque) ?*anyopaque {
const sdf: *SystemDescription = @ptrCast(c_sdf);
const blk = allocator.create(sddf.Blk) catch @panic("OOM");
blk.* = sddf.Blk.init(allocator, sdf, if (c_device) |raw| @ptrCast(raw) else null, @ptrCast(driver), @ptrCast(virt), .{}) catch |e| {
log.err("failed to initialiase blk system: {any}", .{ e });
log.err("failed to initialiase blk system: {any}", .{e});
allocator.destroy(blk);
return null;
};
Expand Down
14 changes: 13 additions & 1 deletion src/data.zig
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,23 @@ pub const Resources = struct {

pub const Timer = struct {
const MAGIC: [5]u8 = MAGIC_START ++ .{0x6};

pub const Client = extern struct {
magic: [5]u8 = MAGIC,
time_page: Region,
virt_id: u8,
};

pub const Virt = extern struct {
magic: [5]u8 = MAGIC,
time_page: Region,
driver_id: u8,
};

pub const Driver = extern struct {
magic: [5]u8 = MAGIC,
time_page: Region,
virt_id: u8,
};
};

pub const Gpu = struct {
Expand Down
5 changes: 3 additions & 2 deletions src/python/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -1104,14 +1104,15 @@ def __init__(
self,
sdf: SystemDescription,
device: Optional[DeviceTree.Node],
driver: SystemDescription.ProtectionDomain
driver: SystemDescription.ProtectionDomain,
virt: SystemDescription.ProtectionDomain
) -> None:
if device is None:
device_obj = None
else:
device_obj = device._obj

self._obj: c_void_p = libsdfgen.sdfgen_sddf_timer(sdf._obj, device_obj, driver._obj)
self._obj: c_void_p = libsdfgen.sdfgen_sddf_timer(sdf._obj, device_obj, driver._obj, virt._obj)

def add_client(self, client: SystemDescription.ProtectionDomain):
ret = libsdfgen.sdfgen_sddf_timer_add_client(self._obj, client._obj)
Expand Down
103 changes: 89 additions & 14 deletions src/sddf/timer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ pub const Timer = struct {
sdf: *SystemDescription,
/// Protection Domain that will act as the driver for the timer
driver: *Pd,
virt: *Pd,
/// Device Tree node for the timer device
device: ?*dtb.Node,
device_res: ConfigResources.Device,
/// Current time page
time_page_size: usize,
/// Config structs
driver_config: ConfigResources.Timer.Driver,
virt_config: ConfigResources.Timer.Virt,
/// Client PDs serviced by the timer driver
clients: std.array_list.Managed(*Pd),
client_configs: std.array_list.Managed(ConfigResources.Timer.Client),
Expand All @@ -35,17 +41,24 @@ pub const Timer = struct {

pub const Error = SystemError;

pub fn init(allocator: Allocator, sdf: *SystemDescription, device: ?*dtb.Node, driver: *Pd) Timer {
// First we have to set some properties on the driver. It is currently our policy that every timer
// driver should be passive.
driver.passive = true;
pub const Options = struct {
time_page_size: usize = 0x1000,
};

pub fn init(allocator: Allocator, sdf: *SystemDescription, device: ?*dtb.Node, driver: *Pd, virt: *Pd, options: Options) Timer {
// Virt should be passive
virt.passive = true;

return .{
.allocator = allocator,
.sdf = sdf,
.driver = driver,
.virt = virt,
.device = device,
.device_res = std.mem.zeroInit(ConfigResources.Device, .{}),
.time_page_size = options.time_page_size,
.driver_config = std.mem.zeroInit(ConfigResources.Timer.Driver, .{}),
.virt_config = std.mem.zeroInit(ConfigResources.Timer.Virt, .{}),
.clients = std.array_list.Managed(*Pd).init(allocator),
.client_configs = std.array_list.Managed(ConfigResources.Timer.Client).init(allocator),
};
Expand All @@ -67,8 +80,17 @@ pub const Timer = struct {
log.err("invalid timer client, same name as driver '{s}", .{client.name});
return Error.InvalidClient;
}
if (std.mem.eql(u8, client.name, system.virt.name)) {
log.err("invalid timer client, same name as virt'{s}", .{client.name});
return Error.InvalidClient;
}
const client_priority = if (client.priority) |priority| priority else Pd.DEFAULT_PRIORITY;
const virt_priority = if (system.virt.priority) |priority| priority else Pd.DEFAULT_PRIORITY;
const driver_priority = if (system.driver.priority) |priority| priority else Pd.DEFAULT_PRIORITY;
if (client_priority >= virt_priority) {
log.err("invalid timer client '{s}', virt '{s}' must have greater priority than client", .{ client.name, system.virt.name });
return Error.InvalidClient;
}
if (client_priority >= driver_priority) {
log.err("invalid timer client '{s}', driver '{s}' must have greater priority than client", .{ client.name, system.driver.name });
return Error.InvalidClient;
Expand All @@ -77,22 +99,73 @@ pub const Timer = struct {
system.client_configs.append(std.mem.zeroInit(ConfigResources.Timer.Client, .{})) catch @panic("Could not add client to Timer");
}

pub fn connectDriver(system: *Timer, mr_time_page: Mr) void {
var sdf = system.sdf;
var driver = system.driver;
var virt = system.virt;

// Create all the MRs between the driver and virtualiser

sdf.addMemoryRegion(mr_time_page);

const driver_map_time_page = Map.create(mr_time_page, driver.getMapVaddr(&mr_time_page), .rw, .{});
driver.addMap(driver_map_time_page);

const virt_map_time_page = Map.create(mr_time_page, virt.getMapVaddr(&mr_time_page), .r, .{});
virt.addMap(virt_map_time_page);

const ch = Channel.create(system.driver, system.virt, .{
// virt must be able to ppc to driver, not notify.
.pp = .b,
.pd_b_notify = false,
}) catch unreachable;
sdf.addChannel(ch);

system.driver_config = .{
.time_page = .createFromMap(driver_map_time_page),
.virt_id = ch.pd_a_id,
};

system.virt_config = .{
.time_page = .createFromMap(virt_map_time_page),
.driver_id = ch.pd_b_id,
};
}

pub fn connectClient(system: *Timer, client: *Pd, i: usize, mr_time_page: Mr) void {
var sdf = system.sdf;
const virt = system.virt;

// system.virt_config.num_clients += 1;

const client_time_page_map = Map.create(mr_time_page, client.getMapVaddr(&mr_time_page), .r, .{});
client.addMap(client_time_page_map);

// Create a channel between the virtualiser and client
const ch = Channel.create(virt, client, .{
.pp = .b,
.pd_b_notify = false,
}) catch unreachable;
sdf.addChannel(ch);

system.client_configs.items[i] = .{
.virt_id = ch.pd_b_id,
.time_page = .createFromMap(client_time_page_map),
};
}

pub fn connect(system: *Timer) !void {
// The driver must be passive
std.debug.assert(system.driver.passive.?);
const allocator = system.allocator;
// The virt must be passive
std.debug.assert(system.virt.passive.?);

const mr_time_page = Mr.create(allocator, "time_page", system.time_page_size, .{});
if (system.device) |dtb_node| {
try sddf.createDriver(system.sdf, system.driver, dtb_node, .timer, &system.device_res);
}
system.connectDriver(mr_time_page);
for (system.clients.items, 0..) |client, i| {
const ch = Channel.create(system.driver, client, .{
// Client needs to be able to PPC into driver
.pp = .b,
// Client does not need to notify driver
.pd_b_notify = false,
}) catch unreachable;
system.sdf.addChannel(ch);
system.client_configs.items[i].driver_id = ch.pd_b_id;
system.connectClient(client, i, mr_time_page);
}

system.connected = true;
Expand All @@ -105,6 +178,8 @@ pub const Timer = struct {

const device_res_data_name = fmt(allocator, "{s}_device_resources", .{system.driver.name});
try data.serialize(allocator, system.device_res, prefix, device_res_data_name);
try data.serialize(allocator, system.driver_config, prefix, "timer_driver");
try data.serialize(allocator, system.virt_config, prefix, "timer_virt");

for (system.clients.items, 0..) |client, i| {
const data_name = fmt(allocator, "timer_client_{s}", .{client.name});
Expand Down
Loading