Update source tree for zig 0.9.1
This commit is contained in:
		
							parent
							
								
									2484cb08d0
								
							
						
					
					
						commit
						06f45400bd
					
				
					 49 changed files with 2347 additions and 2211 deletions
				
			
		
							
								
								
									
										3
									
								
								.github/workflows/main.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/main.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -19,8 +19,7 @@ jobs: | |||
|     - name: Download zig | ||||
|       run: | | ||||
|         export PYTHONIOENCODING=utf8 | ||||
|         # Lock the master commit that we download, because of blocking issues | ||||
|         wget https://ziglang.org/builds/zig-linux-x86_64-0.8.0-dev.2133+ad33e3483.tar.xz | ||||
|         wget https://ziglang.org/download/0.9.1/zig-linux-x86_64-0.9.1.tar.xz | ||||
|         sudo apt-get install mtools | ||||
|         tar -xvf zig* | ||||
|     - name: Install qemu | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ All of these goals will benefit from the features of Zig. | |||
| 
 | ||||
| ## Build | ||||
| 
 | ||||
| Requires a master build of Zig at commit ad33e3483 ([downloaded](https://ziglang.org/builds/zig-linux-x86_64-0.8.0-dev.2133+ad33e3483.tar.xz) or [built from source](https://github.com/ziglang/zig#building-from-source)), *xorriso* and the grub tools (such as *grub-mkrescue*). A *qemu-system* binary compatible with your chosen target is required to run the kernel (e.g. *qemu-system-i386*). | ||||
| Requires a master build of Zig 0.9.1([downloaded](https://ziglang.org/download) or [built from source](https://github.com/ziglang/zig#building-from-source)), *xorriso* and the grub tools (such as *grub-mkrescue*). A *qemu-system* binary compatible with your chosen target is required to run the kernel (e.g. *qemu-system-i386*). | ||||
| 
 | ||||
| ```Shell | ||||
| zig build | ||||
|  |  | |||
							
								
								
									
										29
									
								
								build.zig
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								build.zig
									
										
									
									
									
								
							|  | @ -10,7 +10,7 @@ const Target = std.Target; | |||
| const CrossTarget = std.zig.CrossTarget; | ||||
| const fs = std.fs; | ||||
| const File = fs.File; | ||||
| const Mode = builtin.Mode; | ||||
| const Mode = std.builtin.Mode; | ||||
| const TestMode = rt.TestMode; | ||||
| const ArrayList = std.ArrayList; | ||||
| const Fat32 = @import("mkfat32.zig").Fat32; | ||||
|  | @ -59,14 +59,17 @@ pub fn build(b: *Builder) !void { | |||
|     const disable_display = b.option(bool, "disable-display", "Disable the qemu window") orelse false; | ||||
| 
 | ||||
|     const exec = b.addExecutable("pluto.elf", main_src); | ||||
|     const exec_output_path = try fs.path.join(b.allocator, &[_][]const u8{ b.install_path, "pluto.elf" }); | ||||
|     exec.setOutputDir(b.install_path); | ||||
|     exec.addBuildOption(TestMode, "test_mode", test_mode); | ||||
|     const exec_options = b.addOptions(); | ||||
|     exec.addOptions("build_options", exec_options); | ||||
|     exec_options.addOption(TestMode, "test_mode", test_mode); | ||||
|     exec.setBuildMode(build_mode); | ||||
|     exec.setLinkerScriptPath(linker_script_path); | ||||
|     exec.setLinkerScriptPath(std.build.FileSource{ .path = linker_script_path }); | ||||
|     exec.setTarget(target); | ||||
| 
 | ||||
|     const make_iso = switch (target.getCpuArch()) { | ||||
|         .i386 => b.addSystemCommand(&[_][]const u8{ "./makeiso.sh", boot_path, modules_path, iso_dir_path, exec.getOutputPath(), ramdisk_path, output_iso }), | ||||
|         .i386 => b.addSystemCommand(&[_][]const u8{ "./makeiso.sh", boot_path, modules_path, iso_dir_path, exec_output_path, ramdisk_path, output_iso }), | ||||
|         else => unreachable, | ||||
|     }; | ||||
|     make_iso.step.dependOn(&exec.step); | ||||
|  | @ -85,7 +88,7 @@ pub fn build(b: *Builder) !void { | |||
|         inline for (&[_][]const u8{ "user_program_data", "user_program" }) |user_program| { | ||||
|             // Add some test files for the user mode runtime tests | ||||
|             const user_program_step = b.addExecutable(user_program ++ ".elf", null); | ||||
|             user_program_step.setLinkerScriptPath("test/user_program.ld"); | ||||
|             user_program_step.setLinkerScriptPath(.{ .path = "test/user_program.ld" }); | ||||
|             user_program_step.addAssemblyFile("test/" ++ user_program ++ ".s"); | ||||
|             user_program_step.setOutputDir(b.install_path); | ||||
|             user_program_step.setTarget(target); | ||||
|  | @ -103,18 +106,16 @@ pub fn build(b: *Builder) !void { | |||
|     b.default_step.dependOn(&make_iso.step); | ||||
| 
 | ||||
|     const test_step = b.step("test", "Run tests"); | ||||
|     const mock_path = "../../test/mock/kernel/"; | ||||
|     const arch_mock_path = "../../../../test/mock/kernel/"; | ||||
|     const unit_tests = b.addTest(main_src); | ||||
|     unit_tests.setBuildMode(build_mode); | ||||
|     unit_tests.setMainPkgPath("."); | ||||
|     unit_tests.addBuildOption(TestMode, "test_mode", test_mode); | ||||
|     unit_tests.addBuildOption([]const u8, "mock_path", mock_path); | ||||
|     unit_tests.addBuildOption([]const u8, "arch_mock_path", arch_mock_path); | ||||
|     const unit_test_options = b.addOptions(); | ||||
|     unit_tests.addOptions("build_options", unit_test_options); | ||||
|     unit_test_options.addOption(TestMode, "test_mode", test_mode); | ||||
|     unit_tests.setTarget(.{ .cpu_arch = target.cpu_arch }); | ||||
| 
 | ||||
|     if (builtin.os.tag != .windows) { | ||||
|         unit_tests.enable_qemu = true; | ||||
|         b.enable_qemu = true; | ||||
|     } | ||||
| 
 | ||||
|     // Run the mock gen | ||||
|  | @ -175,7 +176,7 @@ pub fn build(b: *Builder) !void { | |||
|     run_debug_step.dependOn(&qemu_debug_cmd.step); | ||||
| 
 | ||||
|     const debug_step = b.step("debug", "Debug with gdb and connect to a running qemu instance"); | ||||
|     const symbol_file_arg = try std.mem.join(b.allocator, " ", &[_][]const u8{ "symbol-file", exec.getOutputPath() }); | ||||
|     const symbol_file_arg = try std.mem.join(b.allocator, " ", &[_][]const u8{ "symbol-file", exec_output_path }); | ||||
|     const debug_cmd = b.addSystemCommand(&[_][]const u8{ | ||||
|         "gdb-multiarch", | ||||
|         "-ex", | ||||
|  | @ -239,7 +240,7 @@ const Fat32BuilderStep = struct { | |||
|     pub fn create(builder: *Builder, options: Fat32.Options, out_file_path: []const u8) *Fat32BuilderStep { | ||||
|         const fat32_builder_step = builder.allocator.create(Fat32BuilderStep) catch unreachable; | ||||
|         fat32_builder_step.* = .{ | ||||
|             .step = Step.init(.Custom, builder.fmt("Fat32BuilderStep", .{}), builder.allocator, make), | ||||
|             .step = Step.init(.custom, builder.fmt("Fat32BuilderStep", .{}), builder.allocator, make), | ||||
|             .builder = builder, | ||||
|             .options = options, | ||||
|             .out_file_path = out_file_path, | ||||
|  | @ -354,7 +355,7 @@ const RamdiskStep = struct { | |||
|     pub fn create(builder: *Builder, target: CrossTarget, files: []const []const u8, out_file_path: []const u8) *RamdiskStep { | ||||
|         const ramdisk_step = builder.allocator.create(RamdiskStep) catch unreachable; | ||||
|         ramdisk_step.* = .{ | ||||
|             .step = Step.init(.Custom, builder.fmt("Ramdisk", .{}), builder.allocator, make), | ||||
|             .step = Step.init(.custom, builder.fmt("Ramdisk", .{}), builder.allocator, make), | ||||
|             .builder = builder, | ||||
|             .target = target, | ||||
|             .files = files, | ||||
|  |  | |||
							
								
								
									
										19
									
								
								fat32_cp.sh
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								fat32_cp.sh
									
										
									
									
									
								
							|  | @ -1,9 +1,20 @@ | |||
| #!/usr/bin/env bash | ||||
| set -ex | ||||
| 
 | ||||
| IMAGE_PATH_DIR=$1 | ||||
| 
 | ||||
| mkdir test/fat32/mnt | ||||
| sudo mount -o utf8=true $IMAGE_PATH_DIR test/fat32/mnt/ | ||||
| sudo cp -r test/fat32/test_files/. test/fat32/mnt/ | ||||
| sudo umount test/fat32/mnt/ | ||||
| whoami | ||||
| 
 | ||||
| if [ "$(whoami)" = "root" ]; then | ||||
| 	echo "Am root" | ||||
| 	mount -o utf8=true $IMAGE_PATH_DIR test/fat32/mnt/ | ||||
| 	cp -r test/fat32/test_files/. test/fat32/mnt/ | ||||
| 	umount test/fat32/mnt/ | ||||
| else | ||||
| 	echo "Not root" | ||||
| 	sudo mount -o utf8=true $IMAGE_PATH_DIR test/fat32/mnt/ | ||||
| 	sudo cp -r test/fat32/test_files/. test/fat32/mnt/ | ||||
| 	sudo umount test/fat32/mnt/ | ||||
| fi | ||||
| 
 | ||||
| rm -rf test/fat32/mnt | ||||
|  |  | |||
|  | @ -487,7 +487,7 @@ pub const Fat32 = struct { | |||
|                     else => @compileError("Unexpected field type: " ++ @typeName(info.child)), | ||||
|                 }, | ||||
|                 .Int => try fat32_header_stream.writer().writeIntLittle(item.field_type, @field(fat32_header, item.name)), | ||||
|                 else => @compileError("Unexpected field type: " ++ @typeName(info.child)), | ||||
|                 else => @compileError("Unexpected field type: " ++ @typeName(@typeInfo(item.field_type))), | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | @ -567,8 +567,8 @@ pub const Fat32 = struct { | |||
|     ///     @TypeOf(stream).WriteError - Error writing to the stream. | ||||
|     /// | ||||
|     fn clearStream(stream: anytype, size: usize) ErrorSet(@TypeOf(stream))!void { | ||||
|         comptime const buff_size = 4096; | ||||
|         comptime const bytes: [buff_size]u8 = [_]u8{0x00} ** buff_size; | ||||
|         const buff_size = 4096; | ||||
|         const bytes: [buff_size]u8 = [_]u8{0x00} ** buff_size; | ||||
| 
 | ||||
|         var remaining: usize = size; | ||||
|         while (remaining > 0) { | ||||
|  |  | |||
|  | @ -2,9 +2,8 @@ const std = @import("std"); | |||
| const builtin = @import("builtin"); | ||||
| const is_test = builtin.is_test; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.mock_path; | ||||
| 
 | ||||
| pub const internals = if (is_test) @import(mock_path ++ "arch_mock.zig") else switch (builtin.arch) { | ||||
| pub const internals = if (is_test) @import("../../test/mock/kernel/arch_mock.zig") else switch (builtin.cpu.arch) { | ||||
|     .i386 => @import("arch/x86/arch.zig"), | ||||
|     else => unreachable, | ||||
| }; | ||||
|  |  | |||
|  | @ -120,16 +120,16 @@ pub const MEMORY_BLOCK_SIZE: usize = paging.PAGE_SIZE_4KB; | |||
| pub fn in(comptime Type: type, port: u16) Type { | ||||
|     return switch (Type) { | ||||
|         u8 => asm volatile ("inb %[port], %[result]" | ||||
|             : [result] "={al}" (-> Type) | ||||
|             : [port] "N{dx}" (port) | ||||
|             : [result] "={al}" (-> Type), | ||||
|             : [port] "N{dx}" (port), | ||||
|         ), | ||||
|         u16 => asm volatile ("inw %[port], %[result]" | ||||
|             : [result] "={ax}" (-> Type) | ||||
|             : [port] "N{dx}" (port) | ||||
|             : [result] "={ax}" (-> Type), | ||||
|             : [port] "N{dx}" (port), | ||||
|         ), | ||||
|         u32 => asm volatile ("inl %[port], %[result]" | ||||
|             : [result] "={eax}" (-> Type) | ||||
|             : [port] "N{dx}" (port) | ||||
|             : [result] "={eax}" (-> Type), | ||||
|             : [port] "N{dx}" (port), | ||||
|         ), | ||||
|         else => @compileError("Invalid data type. Only u8, u16 or u32, found: " ++ @typeName(Type)), | ||||
|     }; | ||||
|  | @ -147,17 +147,17 @@ pub fn out(port: u16, data: anytype) void { | |||
|         u8 => asm volatile ("outb %[data], %[port]" | ||||
|             : | ||||
|             : [port] "{dx}" (port), | ||||
|               [data] "{al}" (data) | ||||
|               [data] "{al}" (data), | ||||
|         ), | ||||
|         u16 => asm volatile ("outw %[data], %[port]" | ||||
|             : | ||||
|             : [port] "{dx}" (port), | ||||
|               [data] "{ax}" (data) | ||||
|               [data] "{ax}" (data), | ||||
|         ), | ||||
|         u32 => asm volatile ("outl %[data], %[port]" | ||||
|             : | ||||
|             : [port] "{dx}" (port), | ||||
|               [data] "{eax}" (data) | ||||
|               [data] "{eax}" (data), | ||||
|         ), | ||||
|         else => @compileError("Invalid data type. Only u8, u16 or u32, found: " ++ @typeName(@TypeOf(data))), | ||||
|     } | ||||
|  | @ -182,13 +182,13 @@ pub fn lgdt(gdt_ptr: *const gdt.GdtPtr) void { | |||
|     // Load the GDT into the CPU | ||||
|     asm volatile ("lgdt (%%eax)" | ||||
|         : | ||||
|         : [gdt_ptr] "{eax}" (gdt_ptr) | ||||
|         : [gdt_ptr] "{eax}" (gdt_ptr), | ||||
|     ); | ||||
| 
 | ||||
|     // Load the kernel data segment, index into the GDT | ||||
|     asm volatile ("mov %%bx, %%ds" | ||||
|         : | ||||
|         : [KERNEL_DATA_OFFSET] "{bx}" (gdt.KERNEL_DATA_OFFSET) | ||||
|         : [KERNEL_DATA_OFFSET] "{bx}" (gdt.KERNEL_DATA_OFFSET), | ||||
|     ); | ||||
| 
 | ||||
|     asm volatile ("mov %%bx, %%es"); | ||||
|  | @ -212,7 +212,7 @@ pub fn lgdt(gdt_ptr: *const gdt.GdtPtr) void { | |||
| pub fn sgdt() gdt.GdtPtr { | ||||
|     var gdt_ptr = gdt.GdtPtr{ .limit = 0, .base = 0 }; | ||||
|     asm volatile ("sgdt %[tab]" | ||||
|         : [tab] "=m" (gdt_ptr) | ||||
|         : [tab] "=m" (gdt_ptr), | ||||
|     ); | ||||
|     return gdt_ptr; | ||||
| } | ||||
|  | @ -226,7 +226,7 @@ pub fn sgdt() gdt.GdtPtr { | |||
| pub fn ltr(offset: u16) void { | ||||
|     asm volatile ("ltr %%ax" | ||||
|         : | ||||
|         : [offset] "{ax}" (offset) | ||||
|         : [offset] "{ax}" (offset), | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
|  | @ -239,7 +239,7 @@ pub fn ltr(offset: u16) void { | |||
| pub fn lidt(idt_ptr: *const idt.IdtPtr) void { | ||||
|     asm volatile ("lidt (%%eax)" | ||||
|         : | ||||
|         : [idt_ptr] "{eax}" (idt_ptr) | ||||
|         : [idt_ptr] "{eax}" (idt_ptr), | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
|  | @ -252,7 +252,7 @@ pub fn lidt(idt_ptr: *const idt.IdtPtr) void { | |||
| pub fn sidt() idt.IdtPtr { | ||||
|     var idt_ptr = idt.IdtPtr{ .limit = 0, .base = 0 }; | ||||
|     asm volatile ("sidt %[tab]" | ||||
|         : [tab] "=m" (idt_ptr) | ||||
|         : [tab] "=m" (idt_ptr), | ||||
|     ); | ||||
|     return idt_ptr; | ||||
| } | ||||
|  | @ -318,6 +318,8 @@ fn writeSerialCom1(byte: u8) void { | |||
| ///     The Serial instance constructed with the function used to write bytes | ||||
| /// | ||||
| pub fn initSerial(boot_payload: BootPayload) Serial { | ||||
|     // Suppress unused var warning | ||||
|     _ = boot_payload; | ||||
|     serial.init(serial.DEFAULT_BAUDRATE, serial.Port.COM1) catch |e| { | ||||
|         panic(@errorReturnTrace(), "Failed to initialise serial: {}", .{e}); | ||||
|     }; | ||||
|  | @ -336,6 +338,8 @@ pub fn initSerial(boot_payload: BootPayload) Serial { | |||
| ///     The TTY instance constructed with the information required by the rest of the kernel | ||||
| /// | ||||
| pub fn initTTY(boot_payload: BootPayload) TTY { | ||||
|     // Suppress unused var warning | ||||
|     _ = boot_payload; | ||||
|     return .{ | ||||
|         .print = tty.writeString, | ||||
|         .setCursor = tty.setCursor, | ||||
|  | @ -374,7 +378,7 @@ pub fn initMem(mb_info: BootPayload) Allocator.Error!MemProfile { | |||
|     const mmap_addr = mb_info.mmap_addr; | ||||
|     const num_mmap_entries = mb_info.mmap_length / @sizeOf(multiboot.multiboot_memory_map_t); | ||||
| 
 | ||||
|     const allocator = &mem.fixed_buffer_allocator.allocator; | ||||
|     const allocator = mem.fixed_buffer_allocator.allocator(); | ||||
|     var reserved_physical_mem = std.ArrayList(mem.Range).init(allocator); | ||||
|     var reserved_virtual_mem = std.ArrayList(mem.Map).init(allocator); | ||||
|     const mem_map = @intToPtr([*]multiboot.multiboot_memory_map_t, mmap_addr)[0..num_mmap_entries]; | ||||
|  | @ -488,7 +492,7 @@ pub fn initMem(mb_info: BootPayload) Allocator.Error!MemProfile { | |||
| /// x86 initialises the keyboard connected to the PS/2 port | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *std.mem.Allocator - The allocator to use if necessary | ||||
| ///     IN allocator: std.mem.Allocator - The allocator to use if necessary | ||||
| /// | ||||
| /// Return: *Keyboard | ||||
| ///     The initialised PS/2 keyboard | ||||
|  | @ -496,7 +500,7 @@ pub fn initMem(mb_info: BootPayload) Allocator.Error!MemProfile { | |||
| /// Error: std.mem.Allocator.Error | ||||
| ///     OutOfMemory - There wasn't enough memory to allocate what was needed | ||||
| /// | ||||
| pub fn initKeyboard(allocator: *Allocator) Allocator.Error!*Keyboard { | ||||
| pub fn initKeyboard(allocator: Allocator) Allocator.Error!*Keyboard { | ||||
|     return keyboard.init(allocator); | ||||
| } | ||||
| 
 | ||||
|  | @ -510,12 +514,12 @@ pub fn initKeyboard(allocator: *Allocator) Allocator.Error!*Keyboard { | |||
| ///                                the initial CpuState on the kernel stack. | ||||
| ///     IN entry_point: usize    - The pointer to the entry point of the function. Functions only | ||||
| ///                                supported is fn () noreturn | ||||
| ///     IN allocator: *Allocator - The allocator use for allocating a stack. | ||||
| ///     IN allocator: Allocator - The allocator use for allocating a stack. | ||||
| /// | ||||
| /// Error: Allocator.Error | ||||
| ///     OutOfMemory - Unable to allocate space for the stack. | ||||
| /// | ||||
| pub fn initTask(task: *Task, entry_point: usize, allocator: *Allocator) Allocator.Error!void { | ||||
| pub fn initTask(task: *Task, entry_point: usize, allocator: Allocator) Allocator.Error!void { | ||||
|     const data_offset = if (task.kernel) gdt.KERNEL_DATA_OFFSET else gdt.USER_DATA_OFFSET | 0b11; | ||||
|     // Setting the bottom two bits of the code offset designates that this is a ring 3 task | ||||
|     const code_offset = if (task.kernel) gdt.KERNEL_CODE_OFFSET else gdt.USER_CODE_OFFSET | 0b11; | ||||
|  | @ -573,7 +577,7 @@ pub fn initTask(task: *Task, entry_point: usize, allocator: *Allocator) Allocato | |||
| /// Get a list of hardware devices attached to the system. | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *Allocator - An allocator for getting the devices | ||||
| ///     IN allocator: Allocator - An allocator for getting the devices | ||||
| /// | ||||
| /// Return: []Device | ||||
| ///     A list of hardware devices. | ||||
|  | @ -581,7 +585,7 @@ pub fn initTask(task: *Task, entry_point: usize, allocator: *Allocator) Allocato | |||
| /// Error: Allocator.Error | ||||
| ///     OutOfMemory - Unable to allocate space the operation. | ||||
| /// | ||||
| pub fn getDevices(allocator: *Allocator) Allocator.Error![]Device { | ||||
| pub fn getDevices(allocator: Allocator) Allocator.Error![]Device { | ||||
|     return pci.getDevices(allocator); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -107,7 +107,7 @@ export fn start_higher_half() callconv(.Naked) noreturn { | |||
|     // Get the multiboot header address and add the virtual offset | ||||
|     const mb_info_addr = asm ( | ||||
|         \\mov %%ebx, %[res] | ||||
|         : [res] "=r" (-> usize) | ||||
|         : [res] "=r" (-> usize), | ||||
|     ) + @ptrToInt(&KERNEL_ADDR_OFFSET); | ||||
|     kmain(@intToPtr(arch.BootPayload, mb_info_addr)); | ||||
|     while (true) {} | ||||
|  |  | |||
|  | @ -3,8 +3,7 @@ const builtin = @import("builtin"); | |||
| const is_test = builtin.is_test; | ||||
| const expectEqual = std.testing.expectEqual; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| 
 | ||||
| /// The current year to be used for calculating the 4 digit year, as the CMOS return the last two | ||||
| /// digits of the year. | ||||
|  | @ -137,7 +136,7 @@ pub const RtcRegister = enum { | |||
| ///     IN reg: u8                    - The register index to select in the CMOS chip. | ||||
| ///     IN comptime disable_nmi: bool - Whether to disable NMI when selecting a register. | ||||
| /// | ||||
| fn selectRegister(reg: u8, comptime disable_nmi: bool) callconv(.Inline) void { | ||||
| inline fn selectRegister(reg: u8, comptime disable_nmi: bool) void { | ||||
|     if (disable_nmi) { | ||||
|         arch.out(ADDRESS, reg | NMI_BIT); | ||||
|     } else { | ||||
|  | @ -151,7 +150,7 @@ fn selectRegister(reg: u8, comptime disable_nmi: bool) callconv(.Inline) void { | |||
| /// Arguments: | ||||
| ///     IN data: u8 - The data to write to the selected register. | ||||
| /// | ||||
| fn writeRegister(data: u8) callconv(.Inline) void { | ||||
| inline fn writeRegister(data: u8) void { | ||||
|     arch.out(DATA, data); | ||||
| } | ||||
| 
 | ||||
|  | @ -161,7 +160,7 @@ fn writeRegister(data: u8) callconv(.Inline) void { | |||
| /// Return: u8 | ||||
| ///     The value in the selected register. | ||||
| /// | ||||
| fn readRegister() callconv(.Inline) u8 { | ||||
| inline fn readRegister() u8 { | ||||
|     return arch.in(u8, DATA); | ||||
| } | ||||
| 
 | ||||
|  | @ -176,7 +175,7 @@ fn readRegister() callconv(.Inline) u8 { | |||
| /// Return: u8 | ||||
| ///     The value in the selected register. | ||||
| /// | ||||
| fn selectAndReadRegister(reg: u8, comptime disable_nmi: bool) callconv(.Inline) u8 { | ||||
| inline fn selectAndReadRegister(reg: u8, comptime disable_nmi: bool) u8 { | ||||
|     selectRegister(reg, disable_nmi); | ||||
|     arch.ioWait(); | ||||
|     return readRegister(); | ||||
|  | @ -191,7 +190,7 @@ fn selectAndReadRegister(reg: u8, comptime disable_nmi: bool) callconv(.Inline) | |||
| ///     IN data: u8                   - The data to write to the selected register. | ||||
| ///     IN comptime disable_nmi: bool - Whether to disable NMI when selecting a register. | ||||
| /// | ||||
| fn selectAndWriteRegister(reg: u8, data: u8, comptime disable_nmi: bool) callconv(.Inline) void { | ||||
| inline fn selectAndWriteRegister(reg: u8, data: u8, comptime disable_nmi: bool) void { | ||||
|     selectRegister(reg, disable_nmi); | ||||
|     arch.ioWait(); | ||||
|     writeRegister(data); | ||||
|  | @ -278,7 +277,7 @@ test "readRegister" { | |||
|     const expected = @as(u8, 0x55); | ||||
|     const actual = readRegister(); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "selectAndReadRegister NMI" { | ||||
|  | @ -294,7 +293,7 @@ test "selectAndReadRegister NMI" { | |||
|     const expected = @as(u8, 0x44); | ||||
|     const actual = selectAndReadRegister(reg, false); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "selectAndReadRegister no NMI" { | ||||
|  | @ -310,7 +309,7 @@ test "selectAndReadRegister no NMI" { | |||
|     const expected = @as(u8, 0x44); | ||||
|     const actual = selectAndReadRegister(reg, true); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "selectAndWriteRegister NMI" { | ||||
|  | @ -364,7 +363,7 @@ test "readRtcRegister" { | |||
|         const expected = @as(u8, 0x44); | ||||
|         const actual = readRtcRegister(reg); | ||||
| 
 | ||||
|         expectEqual(expected, actual); | ||||
|         try expectEqual(expected, actual); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -389,7 +388,7 @@ test "readStatusRegister NMI" { | |||
|         const expected = @as(u8, 0x78); | ||||
|         const actual = readStatusRegister(reg, false); | ||||
| 
 | ||||
|         expectEqual(expected, actual); | ||||
|         try expectEqual(expected, actual); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -414,7 +413,7 @@ test "readStatusRegister no NMI" { | |||
|         const expected = @as(u8, 0x78); | ||||
|         const actual = readStatusRegister(reg, true); | ||||
| 
 | ||||
|         expectEqual(expected, actual); | ||||
|         try expectEqual(expected, actual); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,8 +6,7 @@ const builtin = @import("builtin"); | |||
| const is_test = builtin.is_test; | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| 
 | ||||
| /// The access bits for a GDT entry. | ||||
| const AccessBits = packed struct { | ||||
|  | @ -427,73 +426,73 @@ pub fn init() void { | |||
| } | ||||
| 
 | ||||
| fn mock_lgdt(ptr: *const GdtPtr) void { | ||||
|     expectEqual(TABLE_SIZE, ptr.limit); | ||||
|     expectEqual(@ptrToInt(&gdt_entries[0]), ptr.base); | ||||
|     expectEqual(TABLE_SIZE, ptr.limit) catch panic(null, "GDT pointer limit was not correct", .{}); | ||||
|     expectEqual(@ptrToInt(&gdt_entries[0]), ptr.base) catch panic(null, "GDT pointer base was not correct", .{}); | ||||
| } | ||||
| 
 | ||||
| test "GDT entries" { | ||||
|     expectEqual(@as(u32, 1), @sizeOf(AccessBits)); | ||||
|     expectEqual(@as(u32, 1), @sizeOf(FlagBits)); | ||||
|     expectEqual(@as(u32, 8), @sizeOf(GdtEntry)); | ||||
|     expectEqual(@as(u32, 104), @sizeOf(Tss)); | ||||
|     expectEqual(@as(u32, 6), @sizeOf(GdtPtr)); | ||||
|     try expectEqual(@as(u32, 1), @sizeOf(AccessBits)); | ||||
|     try expectEqual(@as(u32, 1), @sizeOf(FlagBits)); | ||||
|     try expectEqual(@as(u32, 8), @sizeOf(GdtEntry)); | ||||
|     try expectEqual(@as(u32, 104), @sizeOf(Tss)); | ||||
|     try expectEqual(@as(u32, 6), @sizeOf(GdtPtr)); | ||||
| 
 | ||||
|     const null_entry = gdt_entries[NULL_INDEX]; | ||||
|     expectEqual(@as(u64, 0), @bitCast(u64, null_entry)); | ||||
|     try expectEqual(@as(u64, 0), @bitCast(u64, null_entry)); | ||||
| 
 | ||||
|     const kernel_code_entry = gdt_entries[KERNEL_CODE_INDEX]; | ||||
|     expectEqual(@as(u64, 0xCF9A000000FFFF), @bitCast(u64, kernel_code_entry)); | ||||
|     try expectEqual(@as(u64, 0xCF9A000000FFFF), @bitCast(u64, kernel_code_entry)); | ||||
| 
 | ||||
|     const kernel_data_entry = gdt_entries[KERNEL_DATA_INDEX]; | ||||
|     expectEqual(@as(u64, 0xCF92000000FFFF), @bitCast(u64, kernel_data_entry)); | ||||
|     try expectEqual(@as(u64, 0xCF92000000FFFF), @bitCast(u64, kernel_data_entry)); | ||||
| 
 | ||||
|     const user_code_entry = gdt_entries[USER_CODE_INDEX]; | ||||
|     expectEqual(@as(u64, 0xCFFA000000FFFF), @bitCast(u64, user_code_entry)); | ||||
|     try expectEqual(@as(u64, 0xCFFA000000FFFF), @bitCast(u64, user_code_entry)); | ||||
| 
 | ||||
|     const user_data_entry = gdt_entries[USER_DATA_INDEX]; | ||||
|     expectEqual(@as(u64, 0xCFF2000000FFFF), @bitCast(u64, user_data_entry)); | ||||
|     try expectEqual(@as(u64, 0xCFF2000000FFFF), @bitCast(u64, user_data_entry)); | ||||
| 
 | ||||
|     const tss_entry = gdt_entries[TSS_INDEX]; | ||||
|     expectEqual(@as(u64, 0), @bitCast(u64, tss_entry)); | ||||
|     try expectEqual(@as(u64, 0), @bitCast(u64, tss_entry)); | ||||
| 
 | ||||
|     expectEqual(TABLE_SIZE, gdt_ptr.limit); | ||||
|     try expectEqual(TABLE_SIZE, gdt_ptr.limit); | ||||
| 
 | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.prev_tss); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.esp0); | ||||
|     expectEqual(@as(u32, KERNEL_DATA_OFFSET), main_tss_entry.ss0); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.esp1); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.ss1); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.esp2); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.ss2); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.cr3); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.eip); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.eflags); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.eax); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.ecx); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.edx); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.ebx); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.esp); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.ebp); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.esi); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.edi); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.es); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.cs); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.ss); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.ds); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.fs); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.gs); | ||||
|     expectEqual(@as(u32, 0), main_tss_entry.ldtr); | ||||
|     expectEqual(@as(u16, 0), main_tss_entry.trap); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.prev_tss); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.esp0); | ||||
|     try expectEqual(@as(u32, KERNEL_DATA_OFFSET), main_tss_entry.ss0); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.esp1); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.ss1); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.esp2); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.ss2); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.cr3); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.eip); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.eflags); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.eax); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.ecx); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.edx); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.ebx); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.esp); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.ebp); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.esi); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.edi); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.es); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.cs); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.ss); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.ds); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.fs); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.gs); | ||||
|     try expectEqual(@as(u32, 0), main_tss_entry.ldtr); | ||||
|     try expectEqual(@as(u16, 0), main_tss_entry.trap); | ||||
| 
 | ||||
|     // Size of Tss will fit in a u16 as 104 < 65535 (2^16) | ||||
|     expectEqual(@as(u16, @sizeOf(Tss)), main_tss_entry.io_permissions_base_offset); | ||||
|     try expectEqual(@as(u16, @sizeOf(Tss)), main_tss_entry.io_permissions_base_offset); | ||||
| } | ||||
| 
 | ||||
| test "makeGdtEntry NULL" { | ||||
|     const actual = makeGdtEntry(0, 0, NULL_SEGMENT, NULL_FLAGS); | ||||
| 
 | ||||
|     const expected: u64 = 0; | ||||
|     expectEqual(expected, @bitCast(u64, actual)); | ||||
|     try expectEqual(expected, @bitCast(u64, actual)); | ||||
| } | ||||
| 
 | ||||
| test "makeGdtEntry alternating bit pattern" { | ||||
|  | @ -507,7 +506,7 @@ test "makeGdtEntry alternating bit pattern" { | |||
|         .present = 0, | ||||
|     }; | ||||
| 
 | ||||
|     expectEqual(@as(u8, 0b01010101), @bitCast(u8, alt_access)); | ||||
|     try expectEqual(@as(u8, 0b01010101), @bitCast(u8, alt_access)); | ||||
| 
 | ||||
|     const alt_flag = FlagBits{ | ||||
|         .reserved_zero = 1, | ||||
|  | @ -516,12 +515,12 @@ test "makeGdtEntry alternating bit pattern" { | |||
|         .granularity = 0, | ||||
|     }; | ||||
| 
 | ||||
|     expectEqual(@as(u4, 0b0101), @bitCast(u4, alt_flag)); | ||||
|     try expectEqual(@as(u4, 0b0101), @bitCast(u4, alt_flag)); | ||||
| 
 | ||||
|     const actual = makeGdtEntry(0b01010101010101010101010101010101, 0b01010101010101010101, alt_access, alt_flag); | ||||
| 
 | ||||
|     const expected: u64 = 0b0101010101010101010101010101010101010101010101010101010101010101; | ||||
|     expectEqual(expected, @bitCast(u64, actual)); | ||||
|     try expectEqual(expected, @bitCast(u64, actual)); | ||||
| } | ||||
| 
 | ||||
| test "init" { | ||||
|  | @ -549,7 +548,7 @@ test "init" { | |||
|     // Flags are zero | ||||
|     expected |= @as(u64, @truncate(u8, tss_addr >> 24)) << (16 + 24 + 8 + 4 + 4); | ||||
| 
 | ||||
|     expectEqual(expected, @bitCast(u64, tss_entry)); | ||||
|     try expectEqual(expected, @bitCast(u64, tss_entry)); | ||||
| 
 | ||||
|     // Reset | ||||
|     gdt_ptr.base = 0; | ||||
|  |  | |||
|  | @ -7,9 +7,8 @@ const builtin = @import("builtin"); | |||
| const is_test = builtin.is_test; | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const gdt = if (is_test) @import(mock_path ++ "gdt_mock.zig") else @import("gdt.zig"); | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const gdt = if (is_test) @import("../../../../test/mock/kernel/gdt_mock.zig") else @import("gdt.zig"); | ||||
| const arch = if (builtin.is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| 
 | ||||
| /// The structure that contains all the information that each IDT entry needs. | ||||
| pub const IdtEntry = packed struct { | ||||
|  | @ -196,15 +195,15 @@ fn testHandler0() callconv(.Naked) void {} | |||
| fn testHandler1() callconv(.Naked) void {} | ||||
| 
 | ||||
| fn mock_lidt(ptr: *const IdtPtr) void { | ||||
|     expectEqual(TABLE_SIZE, ptr.limit); | ||||
|     expectEqual(@ptrToInt(&idt_entries[0]), ptr.base); | ||||
|     expectEqual(TABLE_SIZE, ptr.limit) catch panic(null, "IDT pointer limit was not correct", .{}); | ||||
|     expectEqual(@ptrToInt(&idt_entries[0]), ptr.base) catch panic(null, "IDT pointer base was not correct", .{}); | ||||
| } | ||||
| 
 | ||||
| test "IDT entries" { | ||||
|     expectEqual(@as(u32, 8), @sizeOf(IdtEntry)); | ||||
|     expectEqual(@as(u32, 6), @sizeOf(IdtPtr)); | ||||
|     expectEqual(TABLE_SIZE, idt_ptr.limit); | ||||
|     expectEqual(@as(u32, 0), idt_ptr.base); | ||||
|     try expectEqual(@as(u32, 8), @sizeOf(IdtEntry)); | ||||
|     try expectEqual(@as(u32, 6), @sizeOf(IdtPtr)); | ||||
|     try expectEqual(TABLE_SIZE, idt_ptr.limit); | ||||
|     try expectEqual(@as(u32, 0), idt_ptr.base); | ||||
| } | ||||
| 
 | ||||
| test "makeEntry alternating bit pattern" { | ||||
|  | @ -212,7 +211,7 @@ test "makeEntry alternating bit pattern" { | |||
| 
 | ||||
|     const expected: u64 = 0b0101010101010101101001010000000001010101010101010101010101010101; | ||||
| 
 | ||||
|     expectEqual(expected, @bitCast(u64, actual)); | ||||
|     try expectEqual(expected, @bitCast(u64, actual)); | ||||
| } | ||||
| 
 | ||||
| test "isIdtOpen" { | ||||
|  | @ -238,17 +237,16 @@ test "isIdtOpen" { | |||
|         .base_high = 0, | ||||
|     }; | ||||
| 
 | ||||
|     expectEqual(false, isIdtOpen(not_open)); | ||||
|     expectEqual(true, isIdtOpen(open)); | ||||
|     try expectEqual(false, isIdtOpen(not_open)); | ||||
|     try expectEqual(true, isIdtOpen(open)); | ||||
| } | ||||
| 
 | ||||
| test "openInterruptGate" { | ||||
|     const index: u8 = 100; | ||||
|     openInterruptGate(index, testHandler0) catch unreachable; | ||||
|     expectError(IdtError.IdtEntryExists, openInterruptGate(index, testHandler0)); | ||||
|     try expectError(IdtError.IdtEntryExists, openInterruptGate(index, testHandler0)); | ||||
| 
 | ||||
|     const test_fn_0_addr = @ptrToInt(testHandler0); | ||||
|     const test_fn_1_addr = @ptrToInt(testHandler1); | ||||
| 
 | ||||
|     const expected_entry0 = IdtEntry{ | ||||
|         .base_low = @truncate(u16, test_fn_0_addr), | ||||
|  | @ -261,7 +259,7 @@ test "openInterruptGate" { | |||
|         .base_high = @truncate(u16, test_fn_0_addr >> 16), | ||||
|     }; | ||||
| 
 | ||||
|     expectEqual(expected_entry0, idt_entries[index]); | ||||
|     try expectEqual(expected_entry0, idt_entries[index]); | ||||
| 
 | ||||
|     // Reset | ||||
|     idt_entries[index] = IdtEntry{ | ||||
|  | @ -277,7 +275,7 @@ test "openInterruptGate" { | |||
| 
 | ||||
|     openInterruptGate(index, testHandler0) catch unreachable; | ||||
|     // With different handler | ||||
|     expectError(IdtError.IdtEntryExists, openInterruptGate(index, testHandler1)); | ||||
|     try expectError(IdtError.IdtEntryExists, openInterruptGate(index, testHandler1)); | ||||
| 
 | ||||
|     const expected_entry1 = IdtEntry{ | ||||
|         .base_low = @truncate(u16, test_fn_0_addr), | ||||
|  | @ -290,7 +288,7 @@ test "openInterruptGate" { | |||
|         .base_high = @truncate(u16, test_fn_0_addr >> 16), | ||||
|     }; | ||||
| 
 | ||||
|     expectEqual(expected_entry1, idt_entries[index]); | ||||
|     try expectEqual(expected_entry1, idt_entries[index]); | ||||
| 
 | ||||
|     // Reset | ||||
|     idt_entries[index] = IdtEntry{ | ||||
|  | @ -316,7 +314,7 @@ test "init" { | |||
|     init(); | ||||
| 
 | ||||
|     // Post testing | ||||
|     expectEqual(@ptrToInt(&idt_entries), idt_ptr.base); | ||||
|     try expectEqual(@ptrToInt(&idt_entries), idt_ptr.base); | ||||
| 
 | ||||
|     // Reset | ||||
|     idt_ptr.base = 0; | ||||
|  |  | |||
|  | @ -99,7 +99,7 @@ pub fn getInterruptStub(comptime interrupt_num: u32) idt.InterruptHandler { | |||
|                 \\ pushl %[nr] | ||||
|                 \\ jmp commonStub | ||||
|                 : | ||||
|                 : [nr] "n" (interrupt_num) | ||||
|                 : [nr] "n" (interrupt_num), | ||||
|             ); | ||||
|         } | ||||
|     }.func; | ||||
|  |  | |||
|  | @ -7,10 +7,9 @@ const expectError = std.testing.expectError; | |||
| const log = std.log.scoped(.x86_irq); | ||||
| const build_options = @import("build_options"); | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const idt = if (is_test) @import(mock_path ++ "idt_mock.zig") else @import("idt.zig"); | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const pic = if (is_test) @import(mock_path ++ "pic_mock.zig") else @import("pic.zig"); | ||||
| const idt = if (is_test) @import("../../../../test/mock/kernel/idt_mock.zig") else @import("idt.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const pic = if (is_test) @import("../../../../test/mock/kernel/pic_mock.zig") else @import("pic.zig"); | ||||
| const interrupts = @import("interrupts.zig"); | ||||
| 
 | ||||
| /// The error set for the IRQ. This will be from installing a IRQ handler. | ||||
|  | @ -146,10 +145,16 @@ pub fn init() void { | |||
| } | ||||
| 
 | ||||
| fn testFunction0() callconv(.Naked) void {} | ||||
| 
 | ||||
| fn testFunction1(ctx: *arch.CpuState) u32 { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = ctx; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| fn testFunction2(ctx: *arch.CpuState) u32 { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = ctx; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -169,10 +174,10 @@ test "openIrq" { | |||
| test "isValidIrq" { | ||||
|     comptime var i = 0; | ||||
|     inline while (i < NUMBER_OF_ENTRIES) : (i += 1) { | ||||
|         expect(isValidIrq(i)); | ||||
|         try expect(isValidIrq(i)); | ||||
|     } | ||||
| 
 | ||||
|     expect(!isValidIrq(200)); | ||||
|     try expect(!isValidIrq(200)); | ||||
| } | ||||
| 
 | ||||
| test "registerIrq re-register irq handler" { | ||||
|  | @ -184,19 +189,19 @@ test "registerIrq re-register irq handler" { | |||
| 
 | ||||
|     // Pre testing | ||||
|     for (irq_handlers) |h| { | ||||
|         expect(null == h); | ||||
|         try expect(null == h); | ||||
|     } | ||||
| 
 | ||||
|     // Call function | ||||
|     try registerIrq(0, testFunction1); | ||||
|     expectError(IrqError.IrqExists, registerIrq(0, testFunction2)); | ||||
|     try expectError(IrqError.IrqExists, registerIrq(0, testFunction2)); | ||||
| 
 | ||||
|     // Post testing | ||||
|     for (irq_handlers) |h, i| { | ||||
|         if (i != 0) { | ||||
|             expect(null == h); | ||||
|             try expect(null == h); | ||||
|         } else { | ||||
|             expectEqual(testFunction1, h.?); | ||||
|             try expectEqual(testFunction1, h.?); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -213,7 +218,7 @@ test "registerIrq register irq handler" { | |||
| 
 | ||||
|     // Pre testing | ||||
|     for (irq_handlers) |h| { | ||||
|         expect(null == h); | ||||
|         try expect(null == h); | ||||
|     } | ||||
| 
 | ||||
|     // Call function | ||||
|  | @ -222,9 +227,9 @@ test "registerIrq register irq handler" { | |||
|     // Post testing | ||||
|     for (irq_handlers) |h, i| { | ||||
|         if (i != 0) { | ||||
|             expect(null == h); | ||||
|             try expect(null == h); | ||||
|         } else { | ||||
|             expectEqual(testFunction1, h.?); | ||||
|             try expectEqual(testFunction1, h.?); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -233,7 +238,7 @@ test "registerIrq register irq handler" { | |||
| } | ||||
| 
 | ||||
| test "registerIrq invalid irq index" { | ||||
|     expectError(IrqError.InvalidIrq, registerIrq(200, testFunction1)); | ||||
|     try expectError(IrqError.InvalidIrq, registerIrq(200, testFunction1)); | ||||
| } | ||||
| 
 | ||||
| /// | ||||
|  |  | |||
|  | @ -6,11 +6,10 @@ const expectEqual = std.testing.expectEqual; | |||
| const expectError = std.testing.expectError; | ||||
| const log = std.log.scoped(.x86_isr); | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const syscalls = @import("syscalls.zig"); | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| const idt = if (is_test) @import(mock_path ++ "idt_mock.zig") else @import("idt.zig"); | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const idt = if (is_test) @import("../../../../test/mock/kernel/idt_mock.zig") else @import("idt.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const interrupts = @import("interrupts.zig"); | ||||
| 
 | ||||
| /// The error set for the ISR. This will be from installing a ISR handler. | ||||
|  | @ -256,15 +255,23 @@ pub fn init() void { | |||
| 
 | ||||
| fn testFunction0() callconv(.Naked) void {} | ||||
| fn testFunction1(ctx: *arch.CpuState) u32 { | ||||
|     // Suppress unused var warning | ||||
|     _ = ctx; | ||||
|     return 0; | ||||
| } | ||||
| fn testFunction2(ctx: *arch.CpuState) u32 { | ||||
|     // Suppress unused var warning | ||||
|     _ = ctx; | ||||
|     return 0; | ||||
| } | ||||
| fn testFunction3(ctx: *arch.CpuState) u32 { | ||||
|     // Suppress unused var warning | ||||
|     _ = ctx; | ||||
|     return 0; | ||||
| } | ||||
| fn testFunction4(ctx: *arch.CpuState) u32 { | ||||
|     // Suppress unused var warning | ||||
|     _ = ctx; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -284,24 +291,24 @@ test "openIsr" { | |||
| test "isValidIsr" { | ||||
|     comptime var i = 0; | ||||
|     inline while (i < NUMBER_OF_ENTRIES) : (i += 1) { | ||||
|         expectEqual(true, isValidIsr(i)); | ||||
|         try expectEqual(true, isValidIsr(i)); | ||||
|     } | ||||
| 
 | ||||
|     expect(isValidIsr(syscalls.INTERRUPT)); | ||||
|     try expect(isValidIsr(syscalls.INTERRUPT)); | ||||
| 
 | ||||
|     expect(!isValidIsr(200)); | ||||
|     try expect(!isValidIsr(200)); | ||||
| } | ||||
| 
 | ||||
| test "registerIsr re-register syscall handler" { | ||||
|     // Pre testing | ||||
|     expect(null == syscall_handler); | ||||
|     try expect(null == syscall_handler); | ||||
| 
 | ||||
|     // Call function | ||||
|     try registerIsr(syscalls.INTERRUPT, testFunction3); | ||||
|     expectError(IsrError.IsrExists, registerIsr(syscalls.INTERRUPT, testFunction4)); | ||||
|     try expectError(IsrError.IsrExists, registerIsr(syscalls.INTERRUPT, testFunction4)); | ||||
| 
 | ||||
|     // Post testing | ||||
|     expectEqual(testFunction3, syscall_handler.?); | ||||
|     try expectEqual(testFunction3, syscall_handler.?); | ||||
| 
 | ||||
|     // Clean up | ||||
|     syscall_handler = null; | ||||
|  | @ -309,13 +316,13 @@ test "registerIsr re-register syscall handler" { | |||
| 
 | ||||
| test "registerIsr register syscall handler" { | ||||
|     // Pre testing | ||||
|     expect(null == syscall_handler); | ||||
|     try expect(null == syscall_handler); | ||||
| 
 | ||||
|     // Call function | ||||
|     try registerIsr(syscalls.INTERRUPT, testFunction3); | ||||
| 
 | ||||
|     // Post testing | ||||
|     expectEqual(testFunction3, syscall_handler.?); | ||||
|     try expectEqual(testFunction3, syscall_handler.?); | ||||
| 
 | ||||
|     // Clean up | ||||
|     syscall_handler = null; | ||||
|  | @ -324,19 +331,19 @@ test "registerIsr register syscall handler" { | |||
| test "registerIsr re-register isr handler" { | ||||
|     // Pre testing | ||||
|     for (isr_handlers) |h| { | ||||
|         expect(null == h); | ||||
|         try expect(null == h); | ||||
|     } | ||||
| 
 | ||||
|     // Call function | ||||
|     try registerIsr(0, testFunction1); | ||||
|     expectError(IsrError.IsrExists, registerIsr(0, testFunction2)); | ||||
|     try expectError(IsrError.IsrExists, registerIsr(0, testFunction2)); | ||||
| 
 | ||||
|     // Post testing | ||||
|     for (isr_handlers) |h, i| { | ||||
|         if (i != 0) { | ||||
|             expect(null == h); | ||||
|             try expect(null == h); | ||||
|         } else { | ||||
|             expectEqual(testFunction1, h.?); | ||||
|             try expectEqual(testFunction1, h.?); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -347,7 +354,7 @@ test "registerIsr re-register isr handler" { | |||
| test "registerIsr register isr handler" { | ||||
|     // Pre testing | ||||
|     for (isr_handlers) |h| { | ||||
|         expect(null == h); | ||||
|         try expect(null == h); | ||||
|     } | ||||
| 
 | ||||
|     // Call function | ||||
|  | @ -356,9 +363,9 @@ test "registerIsr register isr handler" { | |||
|     // Post testing | ||||
|     for (isr_handlers) |h, i| { | ||||
|         if (i != 0) { | ||||
|             expect(null == h); | ||||
|             try expect(null == h); | ||||
|         } else { | ||||
|             expectEqual(testFunction1, h.?); | ||||
|             try expectEqual(testFunction1, h.?); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -367,7 +374,7 @@ test "registerIsr register isr handler" { | |||
| } | ||||
| 
 | ||||
| test "registerIsr invalid isr index" { | ||||
|     expectError(IsrError.InvalidIsr, registerIsr(200, testFunction1)); | ||||
|     try expectError(IsrError.InvalidIsr, registerIsr(200, testFunction1)); | ||||
| } | ||||
| 
 | ||||
| /// | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ const testing = std.testing; | |||
| const log = std.log.scoped(.x86_keyboard); | ||||
| const irq = @import("irq.zig"); | ||||
| const pic = @import("pic.zig"); | ||||
| const arch = if (builtin.is_test) @import(build_options.arch_mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (builtin.is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| const kb = @import("../../keyboard.zig"); | ||||
| const Keyboard = kb.Keyboard; | ||||
|  | @ -164,7 +164,7 @@ fn onKeyEvent(ctx: *arch.CpuState) usize { | |||
|     const scan_code = readKeyboardBuffer(); | ||||
|     if (parseScanCode(scan_code)) |action| { | ||||
|         if (!keyboard.writeKey(action)) { | ||||
|             log.notice("No room for keyboard action {}\n", .{action}); | ||||
|             log.warn("No room for keyboard action {}\n", .{action}); | ||||
|         } | ||||
|     } | ||||
|     return @ptrToInt(ctx); | ||||
|  | @ -174,7 +174,7 @@ fn onKeyEvent(ctx: *arch.CpuState) usize { | |||
| /// Initialise the PS/2 keyboard | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *Allocator - The allocator to use to create the keyboard instance | ||||
| ///     IN allocator: Allocator - The allocator to use to create the keyboard instance | ||||
| /// | ||||
| /// Return: *Keyboard | ||||
| ///     The keyboard created | ||||
|  | @ -182,7 +182,7 @@ fn onKeyEvent(ctx: *arch.CpuState) usize { | |||
| /// Error: std.mem.Allocator.Error | ||||
| ///     OutOfMemory - There isn't enough memory to allocate the keyboard instance | ||||
| /// | ||||
| pub fn init(allocator: *Allocator) Allocator.Error!*Keyboard { | ||||
| pub fn init(allocator: Allocator) Allocator.Error!*Keyboard { | ||||
|     irq.registerIrq(pic.IRQ_KEYBOARD, onKeyEvent) catch |e| { | ||||
|         panic(@errorReturnTrace(), "Failed to register keyboard IRQ: {}\n", .{e}); | ||||
|     }; | ||||
|  | @ -297,23 +297,23 @@ test "parseScanCode" { | |||
|         var res = parseScanCode(scan_code); | ||||
|         if (key) |k| { | ||||
|             const r = res orelse unreachable; | ||||
|             testing.expectEqual(k, r.position); | ||||
|             testing.expectEqual(false, r.released); | ||||
|             testing.expectEqual(pressed_keys, 1); | ||||
|             try testing.expectEqual(k, r.position); | ||||
|             try testing.expectEqual(false, r.released); | ||||
|             try testing.expectEqual(pressed_keys, 1); | ||||
|         } | ||||
|         testing.expectEqual(on_print_screen, false); | ||||
|         testing.expectEqual(special_sequence, false); | ||||
|         testing.expectEqual(expected_releases, 0); | ||||
|         try testing.expectEqual(on_print_screen, false); | ||||
|         try testing.expectEqual(special_sequence, false); | ||||
|         try testing.expectEqual(expected_releases, 0); | ||||
|         // Test release scan code for key | ||||
|         if (key) |k| { | ||||
|             res = parseScanCode(scan_code | 128); | ||||
|             const r = res orelse unreachable; | ||||
|             testing.expectEqual(k, r.position); | ||||
|             testing.expectEqual(true, r.released); | ||||
|             testing.expectEqual(pressed_keys, 0); | ||||
|             testing.expectEqual(on_print_screen, false); | ||||
|             testing.expectEqual(special_sequence, false); | ||||
|             testing.expectEqual(expected_releases, 0); | ||||
|             try testing.expectEqual(k, r.position); | ||||
|             try testing.expectEqual(true, r.released); | ||||
|             try testing.expectEqual(pressed_keys, 0); | ||||
|             try testing.expectEqual(on_print_screen, false); | ||||
|             try testing.expectEqual(special_sequence, false); | ||||
|             try testing.expectEqual(expected_releases, 0); | ||||
|         } | ||||
|         scan_code += 1; | ||||
|     } | ||||
|  | @ -338,32 +338,32 @@ test "parseScanCode" { | |||
|     }; | ||||
|     const simple_special_codes = &[_]u8{ 72, 75, 77, 80, 82, 71, 73, 83, 79, 81, 53, 28, 56, 91 }; | ||||
|     for (simple_special_keys) |key, i| { | ||||
|         testing.expectEqual(parseScanCode(128), null); | ||||
|         testing.expectEqual(pressed_keys, 0); | ||||
|         testing.expectEqual(on_print_screen, false); | ||||
|         testing.expectEqual(special_sequence, true); | ||||
|         testing.expectEqual(expected_releases, 0); | ||||
|         try testing.expectEqual(parseScanCode(128), null); | ||||
|         try testing.expectEqual(pressed_keys, 0); | ||||
|         try testing.expectEqual(on_print_screen, false); | ||||
|         try testing.expectEqual(special_sequence, true); | ||||
|         try testing.expectEqual(expected_releases, 0); | ||||
| 
 | ||||
|         var res = parseScanCode(simple_special_codes[i]) orelse unreachable; | ||||
|         testing.expectEqual(false, res.released); | ||||
|         testing.expectEqual(key, res.position); | ||||
|         testing.expectEqual(pressed_keys, 1); | ||||
|         testing.expectEqual(on_print_screen, false); | ||||
|         testing.expectEqual(special_sequence, true); | ||||
|         testing.expectEqual(expected_releases, 1); | ||||
|         try testing.expectEqual(false, res.released); | ||||
|         try testing.expectEqual(key, res.position); | ||||
|         try testing.expectEqual(pressed_keys, 1); | ||||
|         try testing.expectEqual(on_print_screen, false); | ||||
|         try testing.expectEqual(special_sequence, true); | ||||
|         try testing.expectEqual(expected_releases, 1); | ||||
| 
 | ||||
|         testing.expectEqual(parseScanCode(128), null); | ||||
|         testing.expectEqual(pressed_keys, 1); | ||||
|         testing.expectEqual(on_print_screen, false); | ||||
|         testing.expectEqual(special_sequence, true); | ||||
|         testing.expectEqual(expected_releases, 0); | ||||
|         try testing.expectEqual(parseScanCode(128), null); | ||||
|         try testing.expectEqual(pressed_keys, 1); | ||||
|         try testing.expectEqual(on_print_screen, false); | ||||
|         try testing.expectEqual(special_sequence, true); | ||||
|         try testing.expectEqual(expected_releases, 0); | ||||
| 
 | ||||
|         res = parseScanCode(simple_special_codes[i] | 128) orelse unreachable; | ||||
|         testing.expectEqual(true, res.released); | ||||
|         testing.expectEqual(key, res.position); | ||||
|         testing.expectEqual(pressed_keys, 0); | ||||
|         testing.expectEqual(on_print_screen, false); | ||||
|         testing.expectEqual(special_sequence, false); | ||||
|         testing.expectEqual(expected_releases, 0); | ||||
|         try testing.expectEqual(true, res.released); | ||||
|         try testing.expectEqual(key, res.position); | ||||
|         try testing.expectEqual(pressed_keys, 0); | ||||
|         try testing.expectEqual(on_print_screen, false); | ||||
|         try testing.expectEqual(special_sequence, false); | ||||
|         try testing.expectEqual(expected_releases, 0); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,3 +1,52 @@ | |||
| pub const __builtin_bswap16 = @import("std").zig.c_builtins.__builtin_bswap16; | ||||
| pub const __builtin_bswap32 = @import("std").zig.c_builtins.__builtin_bswap32; | ||||
| pub const __builtin_bswap64 = @import("std").zig.c_builtins.__builtin_bswap64; | ||||
| pub const __builtin_signbit = @import("std").zig.c_builtins.__builtin_signbit; | ||||
| pub const __builtin_signbitf = @import("std").zig.c_builtins.__builtin_signbitf; | ||||
| pub const __builtin_popcount = @import("std").zig.c_builtins.__builtin_popcount; | ||||
| pub const __builtin_ctz = @import("std").zig.c_builtins.__builtin_ctz; | ||||
| pub const __builtin_clz = @import("std").zig.c_builtins.__builtin_clz; | ||||
| pub const __builtin_sqrt = @import("std").zig.c_builtins.__builtin_sqrt; | ||||
| pub const __builtin_sqrtf = @import("std").zig.c_builtins.__builtin_sqrtf; | ||||
| pub const __builtin_sin = @import("std").zig.c_builtins.__builtin_sin; | ||||
| pub const __builtin_sinf = @import("std").zig.c_builtins.__builtin_sinf; | ||||
| pub const __builtin_cos = @import("std").zig.c_builtins.__builtin_cos; | ||||
| pub const __builtin_cosf = @import("std").zig.c_builtins.__builtin_cosf; | ||||
| pub const __builtin_exp = @import("std").zig.c_builtins.__builtin_exp; | ||||
| pub const __builtin_expf = @import("std").zig.c_builtins.__builtin_expf; | ||||
| pub const __builtin_exp2 = @import("std").zig.c_builtins.__builtin_exp2; | ||||
| pub const __builtin_exp2f = @import("std").zig.c_builtins.__builtin_exp2f; | ||||
| pub const __builtin_log = @import("std").zig.c_builtins.__builtin_log; | ||||
| pub const __builtin_logf = @import("std").zig.c_builtins.__builtin_logf; | ||||
| pub const __builtin_log2 = @import("std").zig.c_builtins.__builtin_log2; | ||||
| pub const __builtin_log2f = @import("std").zig.c_builtins.__builtin_log2f; | ||||
| pub const __builtin_log10 = @import("std").zig.c_builtins.__builtin_log10; | ||||
| pub const __builtin_log10f = @import("std").zig.c_builtins.__builtin_log10f; | ||||
| pub const __builtin_abs = @import("std").zig.c_builtins.__builtin_abs; | ||||
| pub const __builtin_fabs = @import("std").zig.c_builtins.__builtin_fabs; | ||||
| pub const __builtin_fabsf = @import("std").zig.c_builtins.__builtin_fabsf; | ||||
| pub const __builtin_floor = @import("std").zig.c_builtins.__builtin_floor; | ||||
| pub const __builtin_floorf = @import("std").zig.c_builtins.__builtin_floorf; | ||||
| pub const __builtin_ceil = @import("std").zig.c_builtins.__builtin_ceil; | ||||
| pub const __builtin_ceilf = @import("std").zig.c_builtins.__builtin_ceilf; | ||||
| pub const __builtin_trunc = @import("std").zig.c_builtins.__builtin_trunc; | ||||
| pub const __builtin_truncf = @import("std").zig.c_builtins.__builtin_truncf; | ||||
| pub const __builtin_round = @import("std").zig.c_builtins.__builtin_round; | ||||
| pub const __builtin_roundf = @import("std").zig.c_builtins.__builtin_roundf; | ||||
| pub const __builtin_strlen = @import("std").zig.c_builtins.__builtin_strlen; | ||||
| pub const __builtin_strcmp = @import("std").zig.c_builtins.__builtin_strcmp; | ||||
| pub const __builtin_object_size = @import("std").zig.c_builtins.__builtin_object_size; | ||||
| pub const __builtin___memset_chk = @import("std").zig.c_builtins.__builtin___memset_chk; | ||||
| pub const __builtin_memset = @import("std").zig.c_builtins.__builtin_memset; | ||||
| pub const __builtin___memcpy_chk = @import("std").zig.c_builtins.__builtin___memcpy_chk; | ||||
| pub const __builtin_memcpy = @import("std").zig.c_builtins.__builtin_memcpy; | ||||
| pub const __builtin_expect = @import("std").zig.c_builtins.__builtin_expect; | ||||
| pub const __builtin_nanf = @import("std").zig.c_builtins.__builtin_nanf; | ||||
| pub const __builtin_huge_valf = @import("std").zig.c_builtins.__builtin_huge_valf; | ||||
| pub const __builtin_inff = @import("std").zig.c_builtins.__builtin_inff; | ||||
| pub const __builtin_isnan = @import("std").zig.c_builtins.__builtin_isnan; | ||||
| pub const __builtin_isinf = @import("std").zig.c_builtins.__builtin_isinf; | ||||
| pub const __builtin_isinf_sign = @import("std").zig.c_builtins.__builtin_isinf_sign; | ||||
| pub const multiboot_uint8_t = u8; | ||||
| pub const multiboot_uint16_t = c_ushort; | ||||
| pub const multiboot_uint32_t = c_uint; | ||||
|  | @ -30,6 +79,26 @@ pub const struct_multiboot_elf_section_header_table = extern struct { | |||
|     shndx: multiboot_uint32_t, | ||||
| }; | ||||
| pub const multiboot_elf_section_header_table_t = struct_multiboot_elf_section_header_table; | ||||
| const union_unnamed_1 = extern union { | ||||
|     aout_sym: multiboot_aout_symbol_table_t, | ||||
|     elf_sec: multiboot_elf_section_header_table_t, | ||||
| }; | ||||
| const struct_unnamed_3 = extern struct { | ||||
|     framebuffer_palette_addr: multiboot_uint32_t, | ||||
|     framebuffer_palette_num_colors: multiboot_uint16_t, | ||||
| }; | ||||
| const struct_unnamed_4 = extern struct { | ||||
|     framebuffer_red_field_position: multiboot_uint8_t, | ||||
|     framebuffer_red_mask_size: multiboot_uint8_t, | ||||
|     framebuffer_green_field_position: multiboot_uint8_t, | ||||
|     framebuffer_green_mask_size: multiboot_uint8_t, | ||||
|     framebuffer_blue_field_position: multiboot_uint8_t, | ||||
|     framebuffer_blue_mask_size: multiboot_uint8_t, | ||||
| }; | ||||
| const union_unnamed_2 = extern union { | ||||
|     unnamed_0: struct_unnamed_3, | ||||
|     unnamed_1: struct_unnamed_4, | ||||
| }; | ||||
| pub const struct_multiboot_info = extern struct { | ||||
|     flags: multiboot_uint32_t, | ||||
|     mem_lower: multiboot_uint32_t, | ||||
|  | @ -38,10 +107,7 @@ pub const struct_multiboot_info = extern struct { | |||
|     cmdline: multiboot_uint32_t, | ||||
|     mods_count: multiboot_uint32_t, | ||||
|     mods_addr: multiboot_uint32_t, | ||||
|     u: extern union { | ||||
|         aout_sym: multiboot_aout_symbol_table_t, | ||||
|         elf_sec: multiboot_elf_section_header_table_t, | ||||
|     }, | ||||
|     u: union_unnamed_1, | ||||
|     mmap_length: multiboot_uint32_t, | ||||
|     mmap_addr: multiboot_uint32_t, | ||||
|     drives_length: multiboot_uint32_t, | ||||
|  | @ -61,20 +127,7 @@ pub const struct_multiboot_info = extern struct { | |||
|     framebuffer_height: multiboot_uint32_t, | ||||
|     framebuffer_bpp: multiboot_uint8_t, | ||||
|     framebuffer_type: multiboot_uint8_t, | ||||
|     framebuffer: extern union { | ||||
|         framebuffer_palette: extern struct { | ||||
|             framebuffer_palette_addr: multiboot_uint32_t, | ||||
|             framebuffer_palette_num_colors: multiboot_uint16_t, | ||||
|         }, | ||||
|         framebuffer_colours: extern struct { | ||||
|             framebuffer_red_field_position: multiboot_uint8_t, | ||||
|             framebuffer_red_mask_size: multiboot_uint8_t, | ||||
|             framebuffer_green_field_position: multiboot_uint8_t, | ||||
|             framebuffer_green_mask_size: multiboot_uint8_t, | ||||
|             framebuffer_blue_field_position: multiboot_uint8_t, | ||||
|             framebuffer_blue_mask_size: multiboot_uint8_t, | ||||
|         }, | ||||
|     }, | ||||
|     unnamed_0: union_unnamed_2, | ||||
| }; | ||||
| pub const multiboot_info_t = struct_multiboot_info; | ||||
| pub const struct_multiboot_color = extern struct { | ||||
|  | @ -82,7 +135,7 @@ pub const struct_multiboot_color = extern struct { | |||
|     green: multiboot_uint8_t, | ||||
|     blue: multiboot_uint8_t, | ||||
| }; | ||||
| pub const struct_multiboot_mmap_entry = extern struct { | ||||
| pub const struct_multiboot_mmap_entry = packed struct { | ||||
|     size: multiboot_uint32_t, | ||||
|     addr: multiboot_uint64_t, | ||||
|     len: multiboot_uint64_t, | ||||
|  | @ -107,376 +160,416 @@ pub const struct_multiboot_apm_info = extern struct { | |||
|     cseg_16_len: multiboot_uint16_t, | ||||
|     dseg_len: multiboot_uint16_t, | ||||
| }; | ||||
| pub const __GCC_ATOMIC_TEST_AND_SET_TRUEVAL = 1; | ||||
| pub const __BIGGEST_ALIGNMENT__ = 16; | ||||
| pub const __SIZEOF_FLOAT__ = 4; | ||||
| pub const __INT64_FMTd__ = "ld"; | ||||
| pub const __STDC_VERSION__ = @as(c_long, 201112); | ||||
| pub const __INT_LEAST32_FMTi__ = "i"; | ||||
| pub const __tune_znver1__ = 1; | ||||
| pub const __INT_LEAST8_FMTi__ = "hhi"; | ||||
| pub const __LDBL_EPSILON__ = 0.000000; | ||||
| pub const __LZCNT__ = 1; | ||||
| pub const __INT_LEAST32_FMTd__ = "d"; | ||||
| pub const __STDC_UTF_32__ = 1; | ||||
| pub const __SIG_ATOMIC_WIDTH__ = 32; | ||||
| pub const MULTIBOOT_MEMORY_BADRAM = 5; | ||||
| pub const __UINT_FAST64_FMTX__ = "lX"; | ||||
| pub const __GCC_ATOMIC_LLONG_LOCK_FREE = 2; | ||||
| pub const __SEG_FS = 1; | ||||
| pub const __clang_version__ = "9.0.0 (tags/RELEASE_900/final)"; | ||||
| pub const __UINT_LEAST8_FMTo__ = "hho"; | ||||
| pub const __GCC_ASM_FLAG_OUTPUTS__ = 1; | ||||
| pub const __SIZEOF_DOUBLE__ = 8; | ||||
| pub const __INTMAX_FMTd__ = "ld"; | ||||
| pub const __CLANG_ATOMIC_CHAR_LOCK_FREE = 2; | ||||
| pub const __INT_LEAST16_FMTi__ = "hi"; | ||||
| pub const __GCC_ATOMIC_SHORT_LOCK_FREE = 2; | ||||
| pub const __FMA__ = 1; | ||||
| pub const __MMX__ = 1; | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 = 1; | ||||
| pub const __SIZE_FMTX__ = "lX"; | ||||
| pub const __RDSEED__ = 1; | ||||
| pub const __WCHAR_WIDTH__ = 32; | ||||
| pub const __FSGSBASE__ = 1; | ||||
| pub const __PTRDIFF_FMTd__ = "ld"; | ||||
| pub const __DBL_MIN_EXP__ = -1021; | ||||
| pub const __FLT_EVAL_METHOD__ = 0; | ||||
| pub const __SSE_MATH__ = 1; | ||||
| pub const __UINT_FAST8_FMTo__ = "hho"; | ||||
| pub const __UINT_LEAST64_MAX__ = @as(c_ulong, 18446744073709551615); | ||||
| pub const MULTIBOOT_INFO_BOOT_LOADER_NAME = 512; | ||||
| pub const __UINT_LEAST64_FMTx__ = "lx"; | ||||
| pub const __INT8_MAX__ = 127; | ||||
| pub const __znver1 = 1; | ||||
| pub const MULTIBOOT_MEMORY_AVAILABLE = 1; | ||||
| pub const __DBL_HAS_DENORM__ = 1; | ||||
| pub const __FLOAT128__ = 1; | ||||
| pub const __ATOMIC_RELAXED = 0; | ||||
| pub const __DBL_DECIMAL_DIG__ = 17; | ||||
| pub const __XSAVEC__ = 1; | ||||
| pub const MULTIBOOT_SEARCH = 8192; | ||||
| pub const __SIZEOF_SHORT__ = 2; | ||||
| pub const __UINT_FAST16_MAX__ = 65535; | ||||
| pub const __UINT16_FMTX__ = "hX"; | ||||
| pub const __CLANG_ATOMIC_SHORT_LOCK_FREE = 2; | ||||
| pub const __SSSE3__ = 1; | ||||
| pub const __CONSTANT_CFSTRINGS__ = 1; | ||||
| pub const __AVX2__ = 1; | ||||
| pub const __LDBL_MAX_EXP__ = 16384; | ||||
| pub const __WINT_MAX__ = @as(c_uint, 4294967295); | ||||
| pub const __NO_MATH_INLINES = 1; | ||||
| pub const __WCHAR_TYPE__ = int; | ||||
| pub const __LONG_MAX__ = @as(c_long, 9223372036854775807); | ||||
| pub const __STDC_HOSTED__ = 1; | ||||
| pub const MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT = 2; | ||||
| pub const __PTRDIFF_WIDTH__ = 64; | ||||
| pub const __INT_FAST16_FMTi__ = "hi"; | ||||
| pub const __INT_LEAST32_TYPE__ = int; | ||||
| pub const __SCHAR_MAX__ = 127; | ||||
| pub const __LDBL_DENORM_MIN__ = 0.000000; | ||||
| pub const MULTIBOOT_INFO_AOUT_SYMS = 16; | ||||
| pub const __PRFCHW__ = 1; | ||||
| pub const __INT64_C_SUFFIX__ = L; | ||||
| pub const __ELF__ = 1; | ||||
| pub const __LDBL_MANT_DIG__ = 64; | ||||
| pub const MULTIBOOT_HEADER_ALIGN = 4; | ||||
| pub const MULTIBOOT_INFO_CONFIG_TABLE = 256; | ||||
| pub const __CLANG_ATOMIC_INT_LOCK_FREE = 2; | ||||
| pub const __SIZEOF_PTRDIFF_T__ = 8; | ||||
| pub const __SIG_ATOMIC_MAX__ = 2147483647; | ||||
| pub const __UINT64_FMTX__ = "lX"; | ||||
| pub const __UINT64_MAX__ = @as(c_ulong, 18446744073709551615); | ||||
| pub const __DBL_MANT_DIG__ = 53; | ||||
| pub const __FLT_DECIMAL_DIG__ = 9; | ||||
| pub const __INT_LEAST32_MAX__ = 2147483647; | ||||
| pub const __DBL_DIG__ = 15; | ||||
| pub const __ATOMIC_ACQUIRE = 2; | ||||
| pub const __OPENCL_MEMORY_SCOPE_WORK_GROUP = 1; | ||||
| pub const __UINT_FAST16_FMTu__ = "hu"; | ||||
| pub const __INTPTR_FMTi__ = "li"; | ||||
| pub const MULTIBOOT_INFO_MODS = 8; | ||||
| pub const __UINT_FAST8_FMTX__ = "hhX"; | ||||
| pub const __LITTLE_ENDIAN__ = 1; | ||||
| pub const __SSE__ = 1; | ||||
| pub const __FLT_HAS_QUIET_NAN__ = 1; | ||||
| pub const __SIZEOF_SIZE_T__ = 8; | ||||
| pub const __SEG_GS = 1; | ||||
| pub const __UINT_LEAST16_FMTo__ = "ho"; | ||||
| pub const __UINT8_FMTo__ = "hho"; | ||||
| pub const __UINT_LEAST16_FMTx__ = "hx"; | ||||
| pub const __CLANG_ATOMIC_WCHAR_T_LOCK_FREE = 2; | ||||
| pub const __UINT_FAST16_FMTX__ = "hX"; | ||||
| pub const __VERSION__ = "Clang 9.0.0 (tags/RELEASE_900/final)"; | ||||
| pub const __UINT_FAST32_FMTx__ = "x"; | ||||
| pub const __UINTPTR_MAX__ = @as(c_ulong, 18446744073709551615); | ||||
| pub const MULTIBOOT_INFO_ALIGN = 4; | ||||
| pub const __UINT_FAST8_FMTu__ = "hhu"; | ||||
| pub const __UINT_LEAST8_FMTu__ = "hhu"; | ||||
| pub const __UINT_LEAST64_FMTo__ = "lo"; | ||||
| pub const __UINT_LEAST8_MAX__ = 255; | ||||
| pub const __RDRND__ = 1; | ||||
| pub const __SIZEOF_WCHAR_T__ = 4; | ||||
| pub const __MOVBE__ = 1; | ||||
| pub const __LDBL_MAX__ = inf; | ||||
| pub const __UINT16_MAX__ = 65535; | ||||
| pub const _LP64 = 1; | ||||
| pub const __x86_64 = 1; | ||||
| pub const __code_model_small_ = 1; | ||||
| pub const linux = 1; | ||||
| pub const __SIZEOF_WINT_T__ = 4; | ||||
| pub const MULTIBOOT_INFO_CMDLINE = 4; | ||||
| pub const __UINTMAX_FMTo__ = "lo"; | ||||
| pub const __FLT_DIG__ = 6; | ||||
| pub const __UINT_LEAST8_FMTX__ = "hhX"; | ||||
| pub const __INT16_MAX__ = 32767; | ||||
| pub const __WINT_UNSIGNED__ = 1; | ||||
| pub const __FLT_MAX_10_EXP__ = 38; | ||||
| pub const __UINTPTR_FMTX__ = "lX"; | ||||
| pub const __UINT_LEAST16_FMTu__ = "hu"; | ||||
| pub const __CLANG_ATOMIC_POINTER_LOCK_FREE = 2; | ||||
| pub const __WINT_WIDTH__ = 32; | ||||
| pub const __F16C__ = 1; | ||||
| pub const __SHRT_MAX__ = 32767; | ||||
| pub const __znver1__ = 1; | ||||
| pub const __GCC_ATOMIC_BOOL_LOCK_FREE = 2; | ||||
| pub const __POINTER_WIDTH__ = 64; | ||||
| pub const __PTRDIFF_MAX__ = @as(c_long, 9223372036854775807); | ||||
| pub const __INT32_FMTd__ = "d"; | ||||
| pub const __DBL_MIN__ = 0.000000; | ||||
| pub const __SIZEOF_LONG__ = 8; | ||||
| pub const __INTPTR_WIDTH__ = 64; | ||||
| pub const MULTIBOOT_INFO_VBE_INFO = 2048; | ||||
| pub const __INT_FAST32_TYPE__ = int; | ||||
| pub const __NO_INLINE__ = 1; | ||||
| pub const __UINT_FAST32_FMTX__ = "X"; | ||||
| pub const MULTIBOOT_AOUT_KLUDGE = 65536; | ||||
| pub const __gnu_linux__ = 1; | ||||
| pub const __INT_FAST32_MAX__ = 2147483647; | ||||
| pub const __UINTMAX_FMTu__ = "lu"; | ||||
| pub const MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED = 0; | ||||
| pub const __BMI__ = 1; | ||||
| pub const MULTIBOOT_INFO_BOOTDEV = 2; | ||||
| pub const __FLT_RADIX__ = 2; | ||||
| pub const MULTIBOOT_INFO_MEMORY = 1; | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 = 1; | ||||
| pub const MULTIBOOT_FRAMEBUFFER_TYPE_RGB = 1; | ||||
| pub const __GCC_ATOMIC_INT_LOCK_FREE = 2; | ||||
| pub const __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES = 3; | ||||
| pub const __PRAGMA_REDEFINE_EXTNAME = 1; | ||||
| pub const __INT_FAST8_FMTd__ = "hhd"; | ||||
| pub const __INT32_TYPE__ = int; | ||||
| pub const MULTIBOOT_BOOTLOADER_MAGIC = 732803074; | ||||
| pub const __UINTMAX_WIDTH__ = 64; | ||||
| pub const __FLT_MIN__ = 0.000000; | ||||
| pub const __INT64_FMTi__ = "li"; | ||||
| pub const __UINT_FAST64_FMTu__ = "lu"; | ||||
| pub const __INT8_FMTd__ = "hhd"; | ||||
| pub const __INT_FAST16_TYPE__ = short; | ||||
| pub const __FLT_MAX_EXP__ = 128; | ||||
| pub const __XSAVE__ = 1; | ||||
| pub const __DBL_MAX_10_EXP__ = 308; | ||||
| pub const __LDBL_MIN__ = 0.000000; | ||||
| pub const __INT_FAST64_FMTi__ = "li"; | ||||
| pub const __INT_LEAST8_FMTd__ = "hhd"; | ||||
| pub const __CLANG_ATOMIC_LLONG_LOCK_FREE = 2; | ||||
| pub const __UINT_LEAST32_FMTX__ = "X"; | ||||
| pub const __UINTMAX_MAX__ = @as(c_ulong, 18446744073709551615); | ||||
| pub const __UINT_FAST16_FMTo__ = "ho"; | ||||
| pub const __LDBL_DECIMAL_DIG__ = 21; | ||||
| pub const __UINT_LEAST64_FMTX__ = "lX"; | ||||
| pub const __clang_minor__ = 0; | ||||
| pub const __SIZEOF_FLOAT128__ = 16; | ||||
| pub const __UINT_FAST64_FMTo__ = "lo"; | ||||
| pub const __SIZE_FMTx__ = "lx"; | ||||
| pub const __DBL_MAX__ = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878; | ||||
| pub const __DBL_EPSILON__ = 0.000000; | ||||
| pub const __UINT64_FMTx__ = "lx"; | ||||
| pub const MULTIBOOT_HEADER = 1; | ||||
| pub const __CLWB__ = 1; | ||||
| pub const __CHAR_BIT__ = 8; | ||||
| pub const __INT16_FMTi__ = "hi"; | ||||
| pub const _DEBUG = 1; | ||||
| pub const __GNUC_MINOR__ = 2; | ||||
| pub const __UINT_FAST32_MAX__ = @as(c_uint, 4294967295); | ||||
| pub const __UINT8_FMTX__ = "hhX"; | ||||
| pub const __FLT_EPSILON__ = 0.000000; | ||||
| pub const __UINTPTR_WIDTH__ = 64; | ||||
| pub const __llvm__ = 1; | ||||
| pub const __UINT_FAST64_MAX__ = @as(c_ulong, 18446744073709551615); | ||||
| pub const __INT_FAST32_FMTi__ = "i"; | ||||
| pub const __FLT_HAS_INFINITY__ = 1; | ||||
| pub const __AES__ = 1; | ||||
| pub const __UINT8_FMTx__ = "hhx"; | ||||
| pub const __INTMAX_C_SUFFIX__ = L; | ||||
| pub const __ORDER_LITTLE_ENDIAN__ = 1234; | ||||
| pub const __GCC_ATOMIC_CHAR16_T_LOCK_FREE = 2; | ||||
| pub const __INT16_FMTd__ = "hd"; | ||||
| pub const __UINT32_FMTX__ = "X"; | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 = 1; | ||||
| pub const __UINT32_C_SUFFIX__ = U; | ||||
| pub const __INT32_MAX__ = 2147483647; | ||||
| pub const __GCC_ATOMIC_CHAR_LOCK_FREE = 2; | ||||
| pub const __INTMAX_WIDTH__ = 64; | ||||
| pub const __CLANG_ATOMIC_BOOL_LOCK_FREE = 2; | ||||
| pub const __SIZE_FMTo__ = "lo"; | ||||
| pub const __DBL_HAS_QUIET_NAN__ = 1; | ||||
| pub const __INT_FAST8_FMTi__ = "hhi"; | ||||
| pub const __UINT_LEAST32_FMTo__ = "o"; | ||||
| pub const __STDC_UTF_16__ = 1; | ||||
| pub const __UINT_LEAST32_MAX__ = @as(c_uint, 4294967295); | ||||
| pub const __ATOMIC_RELEASE = 3; | ||||
| pub const __UINT_FAST16_FMTx__ = "hx"; | ||||
| pub const __UINTMAX_C_SUFFIX__ = UL; | ||||
| pub const __FLT_MIN_EXP__ = -125; | ||||
| pub const __SIZEOF_LONG_DOUBLE__ = 16; | ||||
| pub const __UINT_LEAST64_FMTu__ = "lu"; | ||||
| pub const MULTIBOOT_MOD_ALIGN = 4096; | ||||
| pub const __GCC_ATOMIC_LONG_LOCK_FREE = 2; | ||||
| pub const __ORDER_PDP_ENDIAN__ = 3412; | ||||
| pub const MULTIBOOT_PAGE_ALIGN = 1; | ||||
| pub const __INT_FAST64_FMTd__ = "ld"; | ||||
| pub const __CLANG_ATOMIC_LONG_LOCK_FREE = 2; | ||||
| pub const __GXX_ABI_VERSION = 1002; | ||||
| pub const __INT16_TYPE__ = short; | ||||
| pub const __MWAITX__ = 1; | ||||
| pub const __SSE2_MATH__ = 1; | ||||
| pub const __FLT_MANT_DIG__ = 24; | ||||
| pub const __UINT_FAST64_FMTx__ = "lx"; | ||||
| pub const __STDC__ = 1; | ||||
| pub const __INT_FAST8_MAX__ = 127; | ||||
| pub const __INTPTR_FMTd__ = "ld"; | ||||
| pub const __GNUC_PATCHLEVEL__ = 1; | ||||
| pub const __UINT_LEAST8_FMTx__ = "hhx"; | ||||
| pub const __SIZE_WIDTH__ = 64; | ||||
| pub const __INT_LEAST64_FMTi__ = "li"; | ||||
| pub const __SSE4_2__ = 1; | ||||
| pub const __AVX__ = 1; | ||||
| pub const __INT_FAST16_MAX__ = 32767; | ||||
| pub const __INTPTR_MAX__ = @as(c_long, 9223372036854775807); | ||||
| pub const __CLANG_ATOMIC_CHAR16_T_LOCK_FREE = 2; | ||||
| pub const __UINT64_FMTu__ = "lu"; | ||||
| pub const __INTMAX_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `L`"); // (no file):67:9 | ||||
| pub const __UINTMAX_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `UL`"); // (no file):73:9 | ||||
| pub const __INT64_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `L`"); // (no file):164:9 | ||||
| pub const __UINT32_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `U`"); // (no file):186:9 | ||||
| pub const __UINT64_C_SUFFIX__ = @compileError("unable to translate macro: undefined identifier `UL`"); // (no file):194:9 | ||||
| pub const __seg_gs = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // (no file):312:9 | ||||
| pub const __seg_fs = @compileError("unable to translate macro: undefined identifier `__attribute__`"); // (no file):313:9 | ||||
| pub const __llvm__ = @as(c_int, 1); | ||||
| pub const __clang__ = @as(c_int, 1); | ||||
| pub const __clang_major__ = @as(c_int, 13); | ||||
| pub const __clang_minor__ = @as(c_int, 0); | ||||
| pub const __clang_patchlevel__ = @as(c_int, 0); | ||||
| pub const __clang_version__ = "13.0.0 (git@github.com:llvm/llvm-project d7b669b3a30345cfcdb2fde2af6f48aa4b94845d)"; | ||||
| pub const __GNUC__ = @as(c_int, 4); | ||||
| pub const __GNUC_MINOR__ = @as(c_int, 2); | ||||
| pub const __GNUC_PATCHLEVEL__ = @as(c_int, 1); | ||||
| pub const __GXX_ABI_VERSION = @as(c_int, 1002); | ||||
| pub const __ATOMIC_RELAXED = @as(c_int, 0); | ||||
| pub const __ATOMIC_CONSUME = @as(c_int, 1); | ||||
| pub const __ATOMIC_ACQUIRE = @as(c_int, 2); | ||||
| pub const __ATOMIC_RELEASE = @as(c_int, 3); | ||||
| pub const __ATOMIC_ACQ_REL = @as(c_int, 4); | ||||
| pub const __ATOMIC_SEQ_CST = @as(c_int, 5); | ||||
| pub const __OPENCL_MEMORY_SCOPE_WORK_ITEM = @as(c_int, 0); | ||||
| pub const __OPENCL_MEMORY_SCOPE_WORK_GROUP = @as(c_int, 1); | ||||
| pub const __OPENCL_MEMORY_SCOPE_DEVICE = @as(c_int, 2); | ||||
| pub const __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES = @as(c_int, 3); | ||||
| pub const __OPENCL_MEMORY_SCOPE_SUB_GROUP = @as(c_int, 4); | ||||
| pub const __PRAGMA_REDEFINE_EXTNAME = @as(c_int, 1); | ||||
| pub const __VERSION__ = "Clang 13.0.0 (git@github.com:llvm/llvm-project d7b669b3a30345cfcdb2fde2af6f48aa4b94845d)"; | ||||
| pub const __OBJC_BOOL_IS_BOOL = @as(c_int, 0); | ||||
| pub const __CONSTANT_CFSTRINGS__ = @as(c_int, 1); | ||||
| pub const __clang_literal_encoding__ = "UTF-8"; | ||||
| pub const __clang_wide_literal_encoding__ = "UTF-32"; | ||||
| pub const __OPTIMIZE__ = @as(c_int, 1); | ||||
| pub const __ORDER_LITTLE_ENDIAN__ = @as(c_int, 1234); | ||||
| pub const __ORDER_BIG_ENDIAN__ = @as(c_int, 4321); | ||||
| pub const __ORDER_PDP_ENDIAN__ = @as(c_int, 3412); | ||||
| pub const __BYTE_ORDER__ = __ORDER_LITTLE_ENDIAN__; | ||||
| pub const __SSE2__ = 1; | ||||
| pub const MULTIBOOT_INFO_FRAMEBUFFER_INFO = 4096; | ||||
| pub const __INT_MAX__ = 2147483647; | ||||
| pub const __INTMAX_FMTi__ = "li"; | ||||
| pub const __DBL_DENORM_MIN__ = 0.000000; | ||||
| pub const MULTIBOOT_INFO_APM_TABLE = 1024; | ||||
| pub const __clang_major__ = 9; | ||||
| pub const __GNUC__ = 4; | ||||
| pub const __UINT32_MAX__ = @as(c_uint, 4294967295); | ||||
| pub const MULTIBOOT_MEMORY_RESERVED = 2; | ||||
| pub const __FLT_DENORM_MIN__ = 0.000000; | ||||
| pub const __DBL_MAX_EXP__ = 1024; | ||||
| pub const __INT8_FMTi__ = "hhi"; | ||||
| pub const __UINT_LEAST16_MAX__ = 65535; | ||||
| pub const __XSAVES__ = 1; | ||||
| pub const __LDBL_HAS_DENORM__ = 1; | ||||
| pub const __LDBL_HAS_QUIET_NAN__ = 1; | ||||
| pub const __UINT_FAST8_MAX__ = 255; | ||||
| pub const __DBL_MIN_10_EXP__ = -307; | ||||
| pub const __UINT8_FMTu__ = "hhu"; | ||||
| pub const __SSE4A__ = 1; | ||||
| pub const __INT_FAST64_MAX__ = @as(c_long, 9223372036854775807); | ||||
| pub const __SSE3__ = 1; | ||||
| pub const __UINT16_FMTu__ = "hu"; | ||||
| pub const __ATOMIC_SEQ_CST = 5; | ||||
| pub const __SIZE_FMTu__ = "lu"; | ||||
| pub const __LDBL_MIN_EXP__ = -16381; | ||||
| pub const __UINT_FAST32_FMTu__ = "u"; | ||||
| pub const __clang_patchlevel__ = 0; | ||||
| pub const __SIZEOF_LONG_LONG__ = 8; | ||||
| pub const __BMI2__ = 1; | ||||
| pub const MULTIBOOT_INFO_ELF_SHDR = 32; | ||||
| pub const __GNUC_STDC_INLINE__ = 1; | ||||
| pub const __PCLMUL__ = 1; | ||||
| pub const __FXSR__ = 1; | ||||
| pub const __UINT8_MAX__ = 255; | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 = 1; | ||||
| pub const __UINT32_FMTx__ = "x"; | ||||
| pub const __UINT16_FMTo__ = "ho"; | ||||
| pub const __POPCNT__ = 1; | ||||
| pub const __OPENCL_MEMORY_SCOPE_DEVICE = 2; | ||||
| pub const MULTIBOOT_VIDEO_MODE = 4; | ||||
| pub const __UINT32_FMTu__ = "u"; | ||||
| pub const __SIZEOF_POINTER__ = 8; | ||||
| pub const __SIZE_MAX__ = @as(c_ulong, 18446744073709551615); | ||||
| pub const __unix = 1; | ||||
| pub const __INT_FAST16_FMTd__ = "hd"; | ||||
| pub const unix = 1; | ||||
| pub const __UINT_LEAST32_FMTu__ = "u"; | ||||
| pub const __FLT_MAX__ = 340282346999999984391321947108527833088.000000; | ||||
| pub const __GCC_ATOMIC_WCHAR_T_LOCK_FREE = 2; | ||||
| pub const __ATOMIC_CONSUME = 1; | ||||
| pub const __unix__ = 1; | ||||
| pub const __x86_64__ = 1; | ||||
| pub const __LDBL_HAS_INFINITY__ = 1; | ||||
| pub const __UINTMAX_FMTx__ = "lx"; | ||||
| pub const __UINT64_C_SUFFIX__ = UL; | ||||
| pub const __FLT_MIN_10_EXP__ = -37; | ||||
| pub const __INT_LEAST16_MAX__ = 32767; | ||||
| pub const __UINT32_FMTo__ = "o"; | ||||
| pub const __UINTPTR_FMTo__ = "lo"; | ||||
| pub const __INT_LEAST16_FMTd__ = "hd"; | ||||
| pub const __UINTPTR_FMTx__ = "lx"; | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 = 1; | ||||
| pub const __INT_LEAST64_FMTd__ = "ld"; | ||||
| pub const __INT_LEAST16_TYPE__ = short; | ||||
| pub const MULTIBOOT_HEADER_MAGIC = 464367618; | ||||
| pub const __ORDER_BIG_ENDIAN__ = 4321; | ||||
| pub const __LDBL_MIN_10_EXP__ = -4931; | ||||
| pub const __INT_LEAST8_MAX__ = 127; | ||||
| pub const __SIZEOF_INT__ = 4; | ||||
| pub const __GCC_ATOMIC_POINTER_LOCK_FREE = 2; | ||||
| pub const MULTIBOOT_INFO_DRIVE_INFO = 128; | ||||
| pub const __SHA__ = 1; | ||||
| pub const MULTIBOOT_MEMORY_INFO = 2; | ||||
| pub const __amd64 = 1; | ||||
| pub const __OBJC_BOOL_IS_BOOL = 0; | ||||
| pub const __ADX__ = 1; | ||||
| pub const __LDBL_MAX_10_EXP__ = 4932; | ||||
| pub const __SIZEOF_INT128__ = 16; | ||||
| pub const __UINT_FAST8_FMTx__ = "hhx"; | ||||
| pub const __CLZERO__ = 1; | ||||
| pub const __linux = 1; | ||||
| pub const __UINT16_FMTx__ = "hx"; | ||||
| pub const __UINTPTR_FMTu__ = "lu"; | ||||
| pub const __UINT_LEAST16_FMTX__ = "hX"; | ||||
| pub const __CLFLUSHOPT__ = 1; | ||||
| pub const __amd64__ = 1; | ||||
| pub const __UINT_FAST32_FMTo__ = "o"; | ||||
| pub const __linux__ = 1; | ||||
| pub const __clang__ = 1; | ||||
| pub const __LP64__ = 1; | ||||
| pub const __PTRDIFF_FMTi__ = "li"; | ||||
| pub const __WBNOINVD__ = 1; | ||||
| pub const __SSE4_1__ = 1; | ||||
| pub const __LDBL_DIG__ = 18; | ||||
| pub const __GCC_ATOMIC_CHAR32_T_LOCK_FREE = 2; | ||||
| pub const __XSAVEOPT__ = 1; | ||||
| pub const __UINT64_FMTo__ = "lo"; | ||||
| pub const __INT_FAST32_FMTd__ = "d"; | ||||
| pub const __ATOMIC_ACQ_REL = 4; | ||||
| pub const MULTIBOOT_MEMORY_ACPI_RECLAIMABLE = 3; | ||||
| pub const __LITTLE_ENDIAN__ = @as(c_int, 1); | ||||
| pub const _LP64 = @as(c_int, 1); | ||||
| pub const __LP64__ = @as(c_int, 1); | ||||
| pub const __CHAR_BIT__ = @as(c_int, 8); | ||||
| pub const __SCHAR_MAX__ = @as(c_int, 127); | ||||
| pub const __SHRT_MAX__ = @as(c_int, 32767); | ||||
| pub const __INT_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal); | ||||
| pub const __LONG_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal); | ||||
| pub const __LONG_LONG_MAX__ = @as(c_longlong, 9223372036854775807); | ||||
| pub const __OPENCL_MEMORY_SCOPE_SUB_GROUP = 4; | ||||
| pub const MULTIBOOT_MEMORY_NVS = 4; | ||||
| pub const __RDPID__ = 1; | ||||
| pub const MULTIBOOT_INFO_MEM_MAP = 64; | ||||
| pub const __INTMAX_MAX__ = @as(c_long, 9223372036854775807); | ||||
| pub const __UINT_LEAST32_FMTx__ = "x"; | ||||
| pub const __WCHAR_MAX__ = 2147483647; | ||||
| pub const __INT64_MAX__ = @as(c_long, 9223372036854775807); | ||||
| pub const __CLANG_ATOMIC_CHAR32_T_LOCK_FREE = 2; | ||||
| pub const __INT_LEAST64_MAX__ = @as(c_long, 9223372036854775807); | ||||
| pub const __WCHAR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal); | ||||
| pub const __WINT_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal); | ||||
| pub const __INTMAX_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal); | ||||
| pub const __SIZE_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal); | ||||
| pub const __UINTMAX_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal); | ||||
| pub const __PTRDIFF_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal); | ||||
| pub const __INTPTR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal); | ||||
| pub const __UINTPTR_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal); | ||||
| pub const __SIZEOF_DOUBLE__ = @as(c_int, 8); | ||||
| pub const __SIZEOF_FLOAT__ = @as(c_int, 4); | ||||
| pub const __SIZEOF_INT__ = @as(c_int, 4); | ||||
| pub const __SIZEOF_LONG__ = @as(c_int, 8); | ||||
| pub const __SIZEOF_LONG_DOUBLE__ = @as(c_int, 16); | ||||
| pub const __SIZEOF_LONG_LONG__ = @as(c_int, 8); | ||||
| pub const __SIZEOF_POINTER__ = @as(c_int, 8); | ||||
| pub const __SIZEOF_SHORT__ = @as(c_int, 2); | ||||
| pub const __SIZEOF_PTRDIFF_T__ = @as(c_int, 8); | ||||
| pub const __SIZEOF_SIZE_T__ = @as(c_int, 8); | ||||
| pub const __SIZEOF_WCHAR_T__ = @as(c_int, 4); | ||||
| pub const __SIZEOF_WINT_T__ = @as(c_int, 4); | ||||
| pub const __SIZEOF_INT128__ = @as(c_int, 16); | ||||
| pub const __INTMAX_TYPE__ = c_long; | ||||
| pub const __INTMAX_FMTd__ = "ld"; | ||||
| pub const __INTMAX_FMTi__ = "li"; | ||||
| pub const __UINTMAX_TYPE__ = c_ulong; | ||||
| pub const __UINTMAX_FMTo__ = "lo"; | ||||
| pub const __UINTMAX_FMTu__ = "lu"; | ||||
| pub const __UINTMAX_FMTx__ = "lx"; | ||||
| pub const __UINTMAX_FMTX__ = "lX"; | ||||
| pub const __OPENCL_MEMORY_SCOPE_WORK_ITEM = 0; | ||||
| pub const __FLT_HAS_DENORM__ = 1; | ||||
| pub const __DECIMAL_DIG__ = __LDBL_DECIMAL_DIG__; | ||||
| pub const __INTMAX_WIDTH__ = @as(c_int, 64); | ||||
| pub const __PTRDIFF_TYPE__ = c_long; | ||||
| pub const __PTRDIFF_FMTd__ = "ld"; | ||||
| pub const __PTRDIFF_FMTi__ = "li"; | ||||
| pub const __PTRDIFF_WIDTH__ = @as(c_int, 64); | ||||
| pub const __INTPTR_TYPE__ = c_long; | ||||
| pub const __INTPTR_FMTd__ = "ld"; | ||||
| pub const __INTPTR_FMTi__ = "li"; | ||||
| pub const __INTPTR_WIDTH__ = @as(c_int, 64); | ||||
| pub const __SIZE_TYPE__ = c_ulong; | ||||
| pub const __SIZE_FMTo__ = "lo"; | ||||
| pub const __SIZE_FMTu__ = "lu"; | ||||
| pub const __SIZE_FMTx__ = "lx"; | ||||
| pub const __SIZE_FMTX__ = "lX"; | ||||
| pub const __SIZE_WIDTH__ = @as(c_int, 64); | ||||
| pub const __WCHAR_TYPE__ = c_int; | ||||
| pub const __WCHAR_WIDTH__ = @as(c_int, 32); | ||||
| pub const __WINT_TYPE__ = c_uint; | ||||
| pub const __WINT_WIDTH__ = @as(c_int, 32); | ||||
| pub const __SIG_ATOMIC_WIDTH__ = @as(c_int, 32); | ||||
| pub const __SIG_ATOMIC_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal); | ||||
| pub const __CHAR16_TYPE__ = c_ushort; | ||||
| pub const __CHAR32_TYPE__ = c_uint; | ||||
| pub const __UINTMAX_WIDTH__ = @as(c_int, 64); | ||||
| pub const __UINTPTR_TYPE__ = c_ulong; | ||||
| pub const __UINTPTR_FMTo__ = "lo"; | ||||
| pub const __UINTPTR_FMTu__ = "lu"; | ||||
| pub const __UINTPTR_FMTx__ = "lx"; | ||||
| pub const __UINTPTR_FMTX__ = "lX"; | ||||
| pub const __UINTPTR_WIDTH__ = @as(c_int, 64); | ||||
| pub const __FLT_DENORM_MIN__ = @as(f32, 1.40129846e-45); | ||||
| pub const __FLT_HAS_DENORM__ = @as(c_int, 1); | ||||
| pub const __FLT_DIG__ = @as(c_int, 6); | ||||
| pub const __FLT_DECIMAL_DIG__ = @as(c_int, 9); | ||||
| pub const __FLT_EPSILON__ = @as(f32, 1.19209290e-7); | ||||
| pub const __FLT_HAS_INFINITY__ = @as(c_int, 1); | ||||
| pub const __FLT_HAS_QUIET_NAN__ = @as(c_int, 1); | ||||
| pub const __FLT_MANT_DIG__ = @as(c_int, 24); | ||||
| pub const __FLT_MAX_10_EXP__ = @as(c_int, 38); | ||||
| pub const __FLT_MAX_EXP__ = @as(c_int, 128); | ||||
| pub const __FLT_MAX__ = @as(f32, 3.40282347e+38); | ||||
| pub const __FLT_MIN_10_EXP__ = -@as(c_int, 37); | ||||
| pub const __FLT_MIN_EXP__ = -@as(c_int, 125); | ||||
| pub const __FLT_MIN__ = @as(f32, 1.17549435e-38); | ||||
| pub const __DBL_DENORM_MIN__ = 4.9406564584124654e-324; | ||||
| pub const __DBL_HAS_DENORM__ = @as(c_int, 1); | ||||
| pub const __DBL_DIG__ = @as(c_int, 15); | ||||
| pub const __DBL_DECIMAL_DIG__ = @as(c_int, 17); | ||||
| pub const __DBL_EPSILON__ = 2.2204460492503131e-16; | ||||
| pub const __DBL_HAS_INFINITY__ = @as(c_int, 1); | ||||
| pub const __DBL_HAS_QUIET_NAN__ = @as(c_int, 1); | ||||
| pub const __DBL_MANT_DIG__ = @as(c_int, 53); | ||||
| pub const __DBL_MAX_10_EXP__ = @as(c_int, 308); | ||||
| pub const __DBL_MAX_EXP__ = @as(c_int, 1024); | ||||
| pub const __DBL_MAX__ = 1.7976931348623157e+308; | ||||
| pub const __DBL_MIN_10_EXP__ = -@as(c_int, 307); | ||||
| pub const __DBL_MIN_EXP__ = -@as(c_int, 1021); | ||||
| pub const __DBL_MIN__ = 2.2250738585072014e-308; | ||||
| pub const __LDBL_DENORM_MIN__ = @as(c_longdouble, 3.64519953188247460253e-4951); | ||||
| pub const __LDBL_HAS_DENORM__ = @as(c_int, 1); | ||||
| pub const __LDBL_DIG__ = @as(c_int, 18); | ||||
| pub const __LDBL_DECIMAL_DIG__ = @as(c_int, 21); | ||||
| pub const __LDBL_EPSILON__ = @as(c_longdouble, 1.08420217248550443401e-19); | ||||
| pub const __LDBL_HAS_INFINITY__ = @as(c_int, 1); | ||||
| pub const __LDBL_HAS_QUIET_NAN__ = @as(c_int, 1); | ||||
| pub const __LDBL_MANT_DIG__ = @as(c_int, 64); | ||||
| pub const __LDBL_MAX_10_EXP__ = @as(c_int, 4932); | ||||
| pub const __LDBL_MAX_EXP__ = @as(c_int, 16384); | ||||
| pub const __LDBL_MAX__ = @as(c_longdouble, 1.18973149535723176502e+4932); | ||||
| pub const __LDBL_MIN_10_EXP__ = -@as(c_int, 4931); | ||||
| pub const __LDBL_MIN_EXP__ = -@as(c_int, 16381); | ||||
| pub const __LDBL_MIN__ = @as(c_longdouble, 3.36210314311209350626e-4932); | ||||
| pub const __POINTER_WIDTH__ = @as(c_int, 64); | ||||
| pub const __BIGGEST_ALIGNMENT__ = @as(c_int, 16); | ||||
| pub const __WINT_UNSIGNED__ = @as(c_int, 1); | ||||
| pub const __INT8_TYPE__ = i8; | ||||
| pub const __INT8_FMTd__ = "hhd"; | ||||
| pub const __INT8_FMTi__ = "hhi"; | ||||
| pub const __INT8_C_SUFFIX__ = ""; | ||||
| pub const __INT16_TYPE__ = c_short; | ||||
| pub const __INT16_FMTd__ = "hd"; | ||||
| pub const __INT16_FMTi__ = "hi"; | ||||
| pub const __INT16_C_SUFFIX__ = ""; | ||||
| pub const __INT32_TYPE__ = c_int; | ||||
| pub const __INT32_FMTd__ = "d"; | ||||
| pub const __INT32_FMTi__ = "i"; | ||||
| pub const __DBL_HAS_INFINITY__ = 1; | ||||
| pub const __FINITE_MATH_ONLY__ = 0; | ||||
| pub const __INT32_C_SUFFIX__ = ""; | ||||
| pub const __INT64_TYPE__ = c_long; | ||||
| pub const __INT64_FMTd__ = "ld"; | ||||
| pub const __INT64_FMTi__ = "li"; | ||||
| pub const __UINT8_TYPE__ = u8; | ||||
| pub const __UINT8_FMTo__ = "hho"; | ||||
| pub const __UINT8_FMTu__ = "hhu"; | ||||
| pub const __UINT8_FMTx__ = "hhx"; | ||||
| pub const __UINT8_FMTX__ = "hhX"; | ||||
| pub const __UINT8_C_SUFFIX__ = ""; | ||||
| pub const __UINT8_MAX__ = @as(c_int, 255); | ||||
| pub const __INT8_MAX__ = @as(c_int, 127); | ||||
| pub const __UINT16_TYPE__ = c_ushort; | ||||
| pub const __UINT16_FMTo__ = "ho"; | ||||
| pub const __UINT16_FMTu__ = "hu"; | ||||
| pub const __UINT16_FMTx__ = "hx"; | ||||
| pub const __UINT16_FMTX__ = "hX"; | ||||
| pub const __UINT16_C_SUFFIX__ = ""; | ||||
| pub const __UINT16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal); | ||||
| pub const __INT16_MAX__ = @as(c_int, 32767); | ||||
| pub const __UINT32_TYPE__ = c_uint; | ||||
| pub const __UINT32_FMTo__ = "o"; | ||||
| pub const __UINT32_FMTu__ = "u"; | ||||
| pub const __UINT32_FMTx__ = "x"; | ||||
| pub const __UINT32_FMTX__ = "X"; | ||||
| pub const __UINT32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal); | ||||
| pub const __INT32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal); | ||||
| pub const __UINT64_TYPE__ = c_ulong; | ||||
| pub const __UINT64_FMTo__ = "lo"; | ||||
| pub const __UINT64_FMTu__ = "lu"; | ||||
| pub const __UINT64_FMTx__ = "lx"; | ||||
| pub const __UINT64_FMTX__ = "lX"; | ||||
| pub const __UINT64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal); | ||||
| pub const __INT64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal); | ||||
| pub const __INT_LEAST8_TYPE__ = i8; | ||||
| pub const __INT_LEAST8_MAX__ = @as(c_int, 127); | ||||
| pub const __INT_LEAST8_FMTd__ = "hhd"; | ||||
| pub const __INT_LEAST8_FMTi__ = "hhi"; | ||||
| pub const __UINT_LEAST8_TYPE__ = u8; | ||||
| pub const __UINT_LEAST8_MAX__ = @as(c_int, 255); | ||||
| pub const __UINT_LEAST8_FMTo__ = "hho"; | ||||
| pub const __UINT_LEAST8_FMTu__ = "hhu"; | ||||
| pub const __UINT_LEAST8_FMTx__ = "hhx"; | ||||
| pub const __UINT_LEAST8_FMTX__ = "hhX"; | ||||
| pub const __INT_LEAST16_TYPE__ = c_short; | ||||
| pub const __INT_LEAST16_MAX__ = @as(c_int, 32767); | ||||
| pub const __INT_LEAST16_FMTd__ = "hd"; | ||||
| pub const __INT_LEAST16_FMTi__ = "hi"; | ||||
| pub const __UINT_LEAST16_TYPE__ = c_ushort; | ||||
| pub const __UINT_LEAST16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal); | ||||
| pub const __UINT_LEAST16_FMTo__ = "ho"; | ||||
| pub const __UINT_LEAST16_FMTu__ = "hu"; | ||||
| pub const __UINT_LEAST16_FMTx__ = "hx"; | ||||
| pub const __UINT_LEAST16_FMTX__ = "hX"; | ||||
| pub const __INT_LEAST32_TYPE__ = c_int; | ||||
| pub const __INT_LEAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal); | ||||
| pub const __INT_LEAST32_FMTd__ = "d"; | ||||
| pub const __INT_LEAST32_FMTi__ = "i"; | ||||
| pub const __UINT_LEAST32_TYPE__ = c_uint; | ||||
| pub const __UINT_LEAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal); | ||||
| pub const __UINT_LEAST32_FMTo__ = "o"; | ||||
| pub const __UINT_LEAST32_FMTu__ = "u"; | ||||
| pub const __UINT_LEAST32_FMTx__ = "x"; | ||||
| pub const __UINT_LEAST32_FMTX__ = "X"; | ||||
| pub const __INT_LEAST64_TYPE__ = c_long; | ||||
| pub const __INT_LEAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal); | ||||
| pub const __INT_LEAST64_FMTd__ = "ld"; | ||||
| pub const __INT_LEAST64_FMTi__ = "li"; | ||||
| pub const __UINT_LEAST64_TYPE__ = c_ulong; | ||||
| pub const __UINT_LEAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal); | ||||
| pub const __UINT_LEAST64_FMTo__ = "lo"; | ||||
| pub const __UINT_LEAST64_FMTu__ = "lu"; | ||||
| pub const __UINT_LEAST64_FMTx__ = "lx"; | ||||
| pub const __UINT_LEAST64_FMTX__ = "lX"; | ||||
| pub const __INT_FAST8_TYPE__ = i8; | ||||
| pub const __INT_FAST8_MAX__ = @as(c_int, 127); | ||||
| pub const __INT_FAST8_FMTd__ = "hhd"; | ||||
| pub const __INT_FAST8_FMTi__ = "hhi"; | ||||
| pub const __UINT_FAST8_TYPE__ = u8; | ||||
| pub const __UINT_FAST8_MAX__ = @as(c_int, 255); | ||||
| pub const __UINT_FAST8_FMTo__ = "hho"; | ||||
| pub const __UINT_FAST8_FMTu__ = "hhu"; | ||||
| pub const __UINT_FAST8_FMTx__ = "hhx"; | ||||
| pub const __UINT_FAST8_FMTX__ = "hhX"; | ||||
| pub const __INT_FAST16_TYPE__ = c_short; | ||||
| pub const __INT_FAST16_MAX__ = @as(c_int, 32767); | ||||
| pub const __INT_FAST16_FMTd__ = "hd"; | ||||
| pub const __INT_FAST16_FMTi__ = "hi"; | ||||
| pub const __UINT_FAST16_TYPE__ = c_ushort; | ||||
| pub const __UINT_FAST16_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 65535, .decimal); | ||||
| pub const __UINT_FAST16_FMTo__ = "ho"; | ||||
| pub const __UINT_FAST16_FMTu__ = "hu"; | ||||
| pub const __UINT_FAST16_FMTx__ = "hx"; | ||||
| pub const __UINT_FAST16_FMTX__ = "hX"; | ||||
| pub const __INT_FAST32_TYPE__ = c_int; | ||||
| pub const __INT_FAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_int, 2147483647, .decimal); | ||||
| pub const __INT_FAST32_FMTd__ = "d"; | ||||
| pub const __INT_FAST32_FMTi__ = "i"; | ||||
| pub const __UINT_FAST32_TYPE__ = c_uint; | ||||
| pub const __UINT_FAST32_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_uint, 4294967295, .decimal); | ||||
| pub const __UINT_FAST32_FMTo__ = "o"; | ||||
| pub const __UINT_FAST32_FMTu__ = "u"; | ||||
| pub const __UINT_FAST32_FMTx__ = "x"; | ||||
| pub const __UINT_FAST32_FMTX__ = "X"; | ||||
| pub const __INT_FAST64_TYPE__ = c_long; | ||||
| pub const __INT_FAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_long, 9223372036854775807, .decimal); | ||||
| pub const __INT_FAST64_FMTd__ = "ld"; | ||||
| pub const __INT_FAST64_FMTi__ = "li"; | ||||
| pub const __UINT_FAST64_TYPE__ = c_ulong; | ||||
| pub const __UINT_FAST64_MAX__ = @import("std").zig.c_translation.promoteIntLiteral(c_ulong, 18446744073709551615, .decimal); | ||||
| pub const __UINT_FAST64_FMTo__ = "lo"; | ||||
| pub const __UINT_FAST64_FMTu__ = "lu"; | ||||
| pub const __UINT_FAST64_FMTx__ = "lx"; | ||||
| pub const __UINT_FAST64_FMTX__ = "lX"; | ||||
| pub const __USER_LABEL_PREFIX__ = ""; | ||||
| pub const __FINITE_MATH_ONLY__ = @as(c_int, 0); | ||||
| pub const __GNUC_STDC_INLINE__ = @as(c_int, 1); | ||||
| pub const __GCC_ATOMIC_TEST_AND_SET_TRUEVAL = @as(c_int, 1); | ||||
| pub const __CLANG_ATOMIC_BOOL_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_CHAR_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_CHAR16_T_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_CHAR32_T_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_WCHAR_T_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_SHORT_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_INT_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_LONG_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_LLONG_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __CLANG_ATOMIC_POINTER_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_BOOL_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_CHAR_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_CHAR16_T_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_CHAR32_T_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_WCHAR_T_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_SHORT_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_INT_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_LONG_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_LLONG_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __GCC_ATOMIC_POINTER_LOCK_FREE = @as(c_int, 2); | ||||
| pub const __FLT_EVAL_METHOD__ = @as(c_int, 0); | ||||
| pub const __FLT_RADIX__ = @as(c_int, 2); | ||||
| pub const __DECIMAL_DIG__ = __LDBL_DECIMAL_DIG__; | ||||
| pub const __GCC_ASM_FLAG_OUTPUTS__ = @as(c_int, 1); | ||||
| pub const __code_model_small__ = @as(c_int, 1); | ||||
| pub const __amd64__ = @as(c_int, 1); | ||||
| pub const __amd64 = @as(c_int, 1); | ||||
| pub const __x86_64 = @as(c_int, 1); | ||||
| pub const __x86_64__ = @as(c_int, 1); | ||||
| pub const __SEG_GS = @as(c_int, 1); | ||||
| pub const __SEG_FS = @as(c_int, 1); | ||||
| pub const __znver2 = @as(c_int, 1); | ||||
| pub const __znver2__ = @as(c_int, 1); | ||||
| pub const __tune_znver2__ = @as(c_int, 1); | ||||
| pub const __REGISTER_PREFIX__ = ""; | ||||
| pub const __NO_MATH_INLINES = @as(c_int, 1); | ||||
| pub const __AES__ = @as(c_int, 1); | ||||
| pub const __PCLMUL__ = @as(c_int, 1); | ||||
| pub const __LAHF_SAHF__ = @as(c_int, 1); | ||||
| pub const __LZCNT__ = @as(c_int, 1); | ||||
| pub const __RDRND__ = @as(c_int, 1); | ||||
| pub const __FSGSBASE__ = @as(c_int, 1); | ||||
| pub const __BMI__ = @as(c_int, 1); | ||||
| pub const __BMI2__ = @as(c_int, 1); | ||||
| pub const __POPCNT__ = @as(c_int, 1); | ||||
| pub const __PRFCHW__ = @as(c_int, 1); | ||||
| pub const __RDSEED__ = @as(c_int, 1); | ||||
| pub const __ADX__ = @as(c_int, 1); | ||||
| pub const __MWAITX__ = @as(c_int, 1); | ||||
| pub const __MOVBE__ = @as(c_int, 1); | ||||
| pub const __SSE4A__ = @as(c_int, 1); | ||||
| pub const __FMA__ = @as(c_int, 1); | ||||
| pub const __F16C__ = @as(c_int, 1); | ||||
| pub const __SHA__ = @as(c_int, 1); | ||||
| pub const __FXSR__ = @as(c_int, 1); | ||||
| pub const __XSAVE__ = @as(c_int, 1); | ||||
| pub const __XSAVEOPT__ = @as(c_int, 1); | ||||
| pub const __XSAVEC__ = @as(c_int, 1); | ||||
| pub const __XSAVES__ = @as(c_int, 1); | ||||
| pub const __CLFLUSHOPT__ = @as(c_int, 1); | ||||
| pub const __CLWB__ = @as(c_int, 1); | ||||
| pub const __WBNOINVD__ = @as(c_int, 1); | ||||
| pub const __CLZERO__ = @as(c_int, 1); | ||||
| pub const __RDPID__ = @as(c_int, 1); | ||||
| pub const __AVX2__ = @as(c_int, 1); | ||||
| pub const __AVX__ = @as(c_int, 1); | ||||
| pub const __SSE4_2__ = @as(c_int, 1); | ||||
| pub const __SSE4_1__ = @as(c_int, 1); | ||||
| pub const __SSSE3__ = @as(c_int, 1); | ||||
| pub const __SSE3__ = @as(c_int, 1); | ||||
| pub const __SSE2__ = @as(c_int, 1); | ||||
| pub const __SSE2_MATH__ = @as(c_int, 1); | ||||
| pub const __SSE__ = @as(c_int, 1); | ||||
| pub const __SSE_MATH__ = @as(c_int, 1); | ||||
| pub const __MMX__ = @as(c_int, 1); | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 = @as(c_int, 1); | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 = @as(c_int, 1); | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 = @as(c_int, 1); | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 = @as(c_int, 1); | ||||
| pub const __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 = @as(c_int, 1); | ||||
| pub const __SIZEOF_FLOAT128__ = @as(c_int, 16); | ||||
| pub const unix = @as(c_int, 1); | ||||
| pub const __unix = @as(c_int, 1); | ||||
| pub const __unix__ = @as(c_int, 1); | ||||
| pub const linux = @as(c_int, 1); | ||||
| pub const __linux = @as(c_int, 1); | ||||
| pub const __linux__ = @as(c_int, 1); | ||||
| pub const __ELF__ = @as(c_int, 1); | ||||
| pub const __gnu_linux__ = @as(c_int, 1); | ||||
| pub const __FLOAT128__ = @as(c_int, 1); | ||||
| pub const __STDC__ = @as(c_int, 1); | ||||
| pub const __STDC_HOSTED__ = @as(c_int, 1); | ||||
| pub const __STDC_VERSION__ = @as(c_long, 201710); | ||||
| pub const __STDC_UTF_16__ = @as(c_int, 1); | ||||
| pub const __STDC_UTF_32__ = @as(c_int, 1); | ||||
| pub const _DEBUG = @as(c_int, 1); | ||||
| pub const __GCC_HAVE_DWARF2_CFI_ASM = @as(c_int, 1); | ||||
| pub const MULTIBOOT_HEADER = @as(c_int, 1); | ||||
| pub const MULTIBOOT_SEARCH = @as(c_int, 8192); | ||||
| pub const MULTIBOOT_HEADER_ALIGN = @as(c_int, 4); | ||||
| pub const MULTIBOOT_HEADER_MAGIC = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x1BADB002, .hexadecimal); | ||||
| pub const MULTIBOOT_BOOTLOADER_MAGIC = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x2BADB002, .hexadecimal); | ||||
| pub const MULTIBOOT_MOD_ALIGN = @as(c_int, 0x00001000); | ||||
| pub const MULTIBOOT_INFO_ALIGN = @as(c_int, 0x00000004); | ||||
| pub const MULTIBOOT_PAGE_ALIGN = @as(c_int, 0x00000001); | ||||
| pub const MULTIBOOT_MEMORY_INFO = @as(c_int, 0x00000002); | ||||
| pub const MULTIBOOT_VIDEO_MODE = @as(c_int, 0x00000004); | ||||
| pub const MULTIBOOT_AOUT_KLUDGE = @import("std").zig.c_translation.promoteIntLiteral(c_int, 0x00010000, .hexadecimal); | ||||
| pub const MULTIBOOT_INFO_MEMORY = @as(c_int, 0x00000001); | ||||
| pub const MULTIBOOT_INFO_BOOTDEV = @as(c_int, 0x00000002); | ||||
| pub const MULTIBOOT_INFO_CMDLINE = @as(c_int, 0x00000004); | ||||
| pub const MULTIBOOT_INFO_MODS = @as(c_int, 0x00000008); | ||||
| pub const MULTIBOOT_INFO_AOUT_SYMS = @as(c_int, 0x00000010); | ||||
| pub const MULTIBOOT_INFO_ELF_SHDR = @as(c_int, 0x00000020); | ||||
| pub const MULTIBOOT_INFO_MEM_MAP = @as(c_int, 0x00000040); | ||||
| pub const MULTIBOOT_INFO_DRIVE_INFO = @as(c_int, 0x00000080); | ||||
| pub const MULTIBOOT_INFO_CONFIG_TABLE = @as(c_int, 0x00000100); | ||||
| pub const MULTIBOOT_INFO_BOOT_LOADER_NAME = @as(c_int, 0x00000200); | ||||
| pub const MULTIBOOT_INFO_APM_TABLE = @as(c_int, 0x00000400); | ||||
| pub const MULTIBOOT_INFO_VBE_INFO = @as(c_int, 0x00000800); | ||||
| pub const MULTIBOOT_INFO_FRAMEBUFFER_INFO = @as(c_int, 0x00001000); | ||||
| pub const MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED = @as(c_int, 0); | ||||
| pub const MULTIBOOT_FRAMEBUFFER_TYPE_RGB = @as(c_int, 1); | ||||
| pub const MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT = @as(c_int, 2); | ||||
| pub const MULTIBOOT_MEMORY_AVAILABLE = @as(c_int, 1); | ||||
| pub const MULTIBOOT_MEMORY_RESERVED = @as(c_int, 2); | ||||
| pub const MULTIBOOT_MEMORY_ACPI_RECLAIMABLE = @as(c_int, 3); | ||||
| pub const MULTIBOOT_MEMORY_NVS = @as(c_int, 4); | ||||
| pub const MULTIBOOT_MEMORY_BADRAM = @as(c_int, 5); | ||||
| pub const multiboot_header = struct_multiboot_header; | ||||
| pub const multiboot_aout_symbol_table = struct_multiboot_aout_symbol_table; | ||||
| pub const multiboot_elf_section_header_table = struct_multiboot_elf_section_header_table; | ||||
|  |  | |||
|  | @ -7,8 +7,7 @@ const builtin = @import("builtin"); | |||
| const is_test = builtin.is_test; | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (builtin.is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const isr = @import("isr.zig"); | ||||
| const MemProfile = @import("../../mem.zig").MemProfile; | ||||
| const tty = @import("../../tty.zig"); | ||||
|  | @ -133,7 +132,7 @@ pub var kernel_directory: Directory align(@truncate(u29, PAGE_SIZE_4KB)) = Direc | |||
| /// Return: usize | ||||
| ///     The index into an array of directory entries. | ||||
| /// | ||||
| fn virtToDirEntryIdx(virt: usize) callconv(.Inline) usize { | ||||
| inline fn virtToDirEntryIdx(virt: usize) usize { | ||||
|     return virt / PAGE_SIZE_4MB; | ||||
| } | ||||
| 
 | ||||
|  | @ -146,7 +145,7 @@ fn virtToDirEntryIdx(virt: usize) callconv(.Inline) usize { | |||
| /// Return: usize | ||||
| ///     The index into an array of table entries. | ||||
| /// | ||||
| fn virtToTableEntryIdx(virt: usize) callconv(.Inline) usize { | ||||
| inline fn virtToTableEntryIdx(virt: usize) usize { | ||||
|     return (virt / PAGE_SIZE_4KB) % ENTRIES_PER_TABLE; | ||||
| } | ||||
| 
 | ||||
|  | @ -157,7 +156,7 @@ fn virtToTableEntryIdx(virt: usize) callconv(.Inline) usize { | |||
| ///     val: *align(1) u32 - The entry to modify | ||||
| ///     attr: u32 - The bits corresponding to the attribute to set | ||||
| /// | ||||
| fn setAttribute(val: *align(1) u32, attr: u32) callconv(.Inline) void { | ||||
| inline fn setAttribute(val: *align(1) u32, attr: u32) void { | ||||
|     val.* |= attr; | ||||
| } | ||||
| 
 | ||||
|  | @ -168,7 +167,7 @@ fn setAttribute(val: *align(1) u32, attr: u32) callconv(.Inline) void { | |||
| ///     val: *align(1) u32 - The entry to modify | ||||
| ///     attr: u32 - The bits corresponding to the attribute to clear | ||||
| /// | ||||
| fn clearAttribute(val: *align(1) u32, attr: u32) callconv(.Inline) void { | ||||
| inline fn clearAttribute(val: *align(1) u32, attr: u32) void { | ||||
|     val.* &= ~attr; | ||||
| } | ||||
| 
 | ||||
|  | @ -182,7 +181,7 @@ fn clearAttribute(val: *align(1) u32, attr: u32) callconv(.Inline) void { | |||
| ///     IN phys_addr: usize - The start of the physical space to map | ||||
| ///     IN phys_end: usize - The end of the physical space to map | ||||
| ///     IN attrs: vmm.Attributes - The attributes to apply to this mapping | ||||
| ///     IN allocator: *Allocator - The allocator to use to map any tables needed | ||||
| ///     IN allocator: Allocator - The allocator to use to map any tables needed | ||||
| ///     OUT dir: *Directory - The directory that this entry is in | ||||
| /// | ||||
| /// Error: vmm.MapperError || Allocator.Error | ||||
|  | @ -193,7 +192,7 @@ fn clearAttribute(val: *align(1) u32, attr: u32) callconv(.Inline) void { | |||
| ///     vmm.MapperError.MisalignedVirtualAddress - One or both of the virtual addresses aren't page size aligned | ||||
| ///     Allocator.Error.* - See Allocator.alignedAlloc | ||||
| /// | ||||
| fn mapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, phys_start: usize, phys_end: usize, attrs: vmm.Attributes, allocator: *Allocator) (vmm.MapperError || Allocator.Error)!void { | ||||
| fn mapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, phys_start: usize, phys_end: usize, attrs: vmm.Attributes, allocator: Allocator) (vmm.MapperError || Allocator.Error)!void { | ||||
|     if (phys_start > phys_end) { | ||||
|         return vmm.MapperError.InvalidPhysicalAddress; | ||||
|     } | ||||
|  | @ -271,12 +270,14 @@ fn mapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, phys_start: | |||
| ///     IN virt_addr: usize - The start of the virtual space to map | ||||
| ///     IN virt_end: usize - The end of the virtual space to map | ||||
| ///     OUT dir: *Directory - The directory that this entry is in | ||||
| ///     IN allocator: *Allocator - The allocator used to map the region to be freed. | ||||
| ///     IN allocator: Allocator - The allocator used to map the region to be freed. | ||||
| /// | ||||
| /// Error: vmm.MapperError | ||||
| ///     vmm.MapperError.NotMapped - If the region being unmapped wasn't mapped in the first place | ||||
| /// | ||||
| fn unmapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, allocator: *Allocator) vmm.MapperError!void { | ||||
| fn unmapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, allocator: Allocator) vmm.MapperError!void { | ||||
|     // Suppress unused var warning | ||||
|     _ = allocator; | ||||
|     const entry = virtToDirEntryIdx(virt_start); | ||||
|     const table = dir.tables[entry] orelse return vmm.MapperError.NotMapped; | ||||
|     var addr = virt_start; | ||||
|  | @ -287,7 +288,7 @@ fn unmapDirEntry(dir: *Directory, virt_start: usize, virt_end: usize, allocator: | |||
|             if (dir == &kernel_directory) { | ||||
|                 asm volatile ("invlpg (%[addr])" | ||||
|                     : | ||||
|                     : [addr] "r" (addr) | ||||
|                     : [addr] "r" (addr), | ||||
|                     : "memory" | ||||
|                 ); | ||||
|             } | ||||
|  | @ -341,7 +342,7 @@ fn mapTableEntry(dir: *const Directory, entry: *align(1) TableEntry, virt_addr: | |||
|     if (dir == &kernel_directory) { | ||||
|         asm volatile ("invlpg (%[addr])" | ||||
|             : | ||||
|             : [addr] "r" (virt_addr) | ||||
|             : [addr] "r" (virt_addr), | ||||
|             : "memory" | ||||
|         ); | ||||
|     } | ||||
|  | @ -360,13 +361,13 @@ fn mapTableEntry(dir: *const Directory, entry: *align(1) TableEntry, virt_addr: | |||
| ///     IN physical_start: usize - The start of the physical region to map to | ||||
| ///     IN physical_end: usize - The end (exclusive) of the physical region to map to | ||||
| ///     IN attrs: vmm.Attributes - The attributes to apply to this mapping | ||||
| ///     IN/OUT allocator: *Allocator - The allocator to use to allocate any intermediate data structures required to map this region | ||||
| ///     IN/OUT allocator: Allocator - The allocator to use to allocate any intermediate data structures required to map this region | ||||
| ///     IN/OUT dir: *Directory - The page directory to map within | ||||
| /// | ||||
| /// Error: vmm.MapperError || Allocator.Error | ||||
| ///     * - See mapDirEntry | ||||
| /// | ||||
| pub fn map(virtual_start: usize, virtual_end: usize, phys_start: usize, phys_end: usize, attrs: vmm.Attributes, allocator: *Allocator, dir: *Directory) (Allocator.Error || vmm.MapperError)!void { | ||||
| pub fn map(virtual_start: usize, virtual_end: usize, phys_start: usize, phys_end: usize, attrs: vmm.Attributes, allocator: Allocator, dir: *Directory) (Allocator.Error || vmm.MapperError)!void { | ||||
|     var virt_addr = virtual_start; | ||||
|     var phys_addr = phys_start; | ||||
|     var virt_next = std.math.min(virtual_end, std.mem.alignBackward(virt_addr, PAGE_SIZE_4MB) + PAGE_SIZE_4MB); | ||||
|  | @ -394,7 +395,7 @@ pub fn map(virtual_start: usize, virtual_end: usize, phys_start: usize, phys_end | |||
| /// Error: vmm.MapperError | ||||
| ///     vmm.MapperError.NotMapped - If the region being unmapped wasn't mapped in the first place | ||||
| /// | ||||
| pub fn unmap(virtual_start: usize, virtual_end: usize, allocator: *Allocator, dir: *Directory) vmm.MapperError!void { | ||||
| pub fn unmap(virtual_start: usize, virtual_end: usize, allocator: Allocator, dir: *Directory) vmm.MapperError!void { | ||||
|     var virt_addr = virtual_start; | ||||
|     var virt_next = std.math.min(virtual_end, std.mem.alignBackward(virt_addr, PAGE_SIZE_4MB) + PAGE_SIZE_4MB); | ||||
|     var entry_idx = virtToDirEntryIdx(virt_addr); | ||||
|  | @ -423,16 +424,16 @@ pub fn unmap(virtual_start: usize, virtual_end: usize, allocator: *Allocator, di | |||
| fn pageFault(state: *arch.CpuState) u32 { | ||||
|     log.info("State: {X}\n", .{state}); | ||||
|     var cr0 = asm volatile ("mov %%cr0, %[cr0]" | ||||
|         : [cr0] "=r" (-> u32) | ||||
|         : [cr0] "=r" (-> u32), | ||||
|     ); | ||||
|     var cr2 = asm volatile ("mov %%cr2, %[cr2]" | ||||
|         : [cr2] "=r" (-> u32) | ||||
|         : [cr2] "=r" (-> u32), | ||||
|     ); | ||||
|     var cr3 = asm volatile ("mov %%cr3, %[cr3]" | ||||
|         : [cr3] "=r" (-> u32) | ||||
|         : [cr3] "=r" (-> u32), | ||||
|     ); | ||||
|     var cr4 = asm volatile ("mov %%cr4, %[cr4]" | ||||
|         : [cr4] "=r" (-> u32) | ||||
|         : [cr4] "=r" (-> u32), | ||||
|     ); | ||||
|     log.info("CR0: 0x{X}, CR2: 0x{X}, CR3: 0x{X}, CR4: 0x{X}\n", .{ cr0, cr2, cr3, cr4 }); | ||||
|     @panic("Page fault"); | ||||
|  | @ -454,7 +455,7 @@ pub fn init(mem_profile: *const MemProfile) void { | |||
|     const dir_physaddr = @ptrToInt(mem.virtToPhys(&kernel_directory)); | ||||
|     asm volatile ("mov %[addr], %%cr3" | ||||
|         : | ||||
|         : [addr] "{eax}" (dir_physaddr) | ||||
|         : [addr] "{eax}" (dir_physaddr), | ||||
|     ); | ||||
|     const v_end = std.mem.alignForward(@ptrToInt(mem_profile.vaddr_end), PAGE_SIZE_4KB); | ||||
|     switch (build_options.test_mode) { | ||||
|  | @ -463,14 +464,14 @@ pub fn init(mem_profile: *const MemProfile) void { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| fn checkDirEntry(entry: DirectoryEntry, virt_start: usize, virt_end: usize, phys_start: usize, attrs: vmm.Attributes, table: *Table, present: bool) void { | ||||
|     expectEqual(entry & DENTRY_PRESENT, if (present) DENTRY_PRESENT else 0); | ||||
|     expectEqual(entry & DENTRY_WRITABLE, if (attrs.writable) DENTRY_WRITABLE else 0); | ||||
|     expectEqual(entry & DENTRY_USER, if (attrs.kernel) 0 else DENTRY_USER); | ||||
|     expectEqual(entry & DENTRY_WRITE_THROUGH, DENTRY_WRITE_THROUGH); | ||||
|     expectEqual(entry & DENTRY_CACHE_DISABLED, if (attrs.cachable) 0 else DENTRY_CACHE_DISABLED); | ||||
|     expectEqual(entry & DENTRY_4MB_PAGES, 0); | ||||
|     expectEqual(entry & DENTRY_ZERO, 0); | ||||
| fn checkDirEntry(entry: DirectoryEntry, virt_start: usize, virt_end: usize, phys_start: usize, attrs: vmm.Attributes, table: *Table, present: bool) !void { | ||||
|     try expectEqual(entry & DENTRY_PRESENT, if (present) DENTRY_PRESENT else 0); | ||||
|     try expectEqual(entry & DENTRY_WRITABLE, if (attrs.writable) DENTRY_WRITABLE else 0); | ||||
|     try expectEqual(entry & DENTRY_USER, if (attrs.kernel) 0 else DENTRY_USER); | ||||
|     try expectEqual(entry & DENTRY_WRITE_THROUGH, DENTRY_WRITE_THROUGH); | ||||
|     try expectEqual(entry & DENTRY_CACHE_DISABLED, if (attrs.cachable) 0 else DENTRY_CACHE_DISABLED); | ||||
|     try expectEqual(entry & DENTRY_4MB_PAGES, 0); | ||||
|     try expectEqual(entry & DENTRY_ZERO, 0); | ||||
| 
 | ||||
|     var tentry_idx = virtToTableEntryIdx(virt_start); | ||||
|     var tentry_idx_end = virtToTableEntryIdx(virt_end); | ||||
|  | @ -480,19 +481,19 @@ fn checkDirEntry(entry: DirectoryEntry, virt_start: usize, virt_end: usize, phys | |||
|         phys += PAGE_SIZE_4KB; | ||||
|     }) { | ||||
|         const tentry = table.entries[tentry_idx]; | ||||
|         checkTableEntry(tentry, phys, attrs, present); | ||||
|         try checkTableEntry(tentry, phys, attrs, present); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn checkTableEntry(entry: TableEntry, page_phys: usize, attrs: vmm.Attributes, present: bool) void { | ||||
|     expectEqual(entry & TENTRY_PRESENT, if (present) TENTRY_PRESENT else 0); | ||||
|     expectEqual(entry & TENTRY_WRITABLE, if (attrs.writable) TENTRY_WRITABLE else 0); | ||||
|     expectEqual(entry & TENTRY_USER, if (attrs.kernel) 0 else TENTRY_USER); | ||||
|     expectEqual(entry & TENTRY_WRITE_THROUGH, TENTRY_WRITE_THROUGH); | ||||
|     expectEqual(entry & TENTRY_CACHE_DISABLED, if (attrs.cachable) 0 else TENTRY_CACHE_DISABLED); | ||||
|     expectEqual(entry & TENTRY_ZERO, 0); | ||||
|     expectEqual(entry & TENTRY_GLOBAL, 0); | ||||
|     expectEqual(entry & TENTRY_PAGE_ADDR, page_phys); | ||||
| fn checkTableEntry(entry: TableEntry, page_phys: usize, attrs: vmm.Attributes, present: bool) !void { | ||||
|     try expectEqual(entry & TENTRY_PRESENT, if (present) TENTRY_PRESENT else 0); | ||||
|     try expectEqual(entry & TENTRY_WRITABLE, if (attrs.writable) TENTRY_WRITABLE else 0); | ||||
|     try expectEqual(entry & TENTRY_USER, if (attrs.kernel) 0 else TENTRY_USER); | ||||
|     try expectEqual(entry & TENTRY_WRITE_THROUGH, TENTRY_WRITE_THROUGH); | ||||
|     try expectEqual(entry & TENTRY_CACHE_DISABLED, if (attrs.cachable) 0 else TENTRY_CACHE_DISABLED); | ||||
|     try expectEqual(entry & TENTRY_ZERO, 0); | ||||
|     try expectEqual(entry & TENTRY_GLOBAL, 0); | ||||
|     try expectEqual(entry & TENTRY_PAGE_ADDR, page_phys); | ||||
| } | ||||
| 
 | ||||
| test "setAttribute and clearAttribute" { | ||||
|  | @ -502,35 +503,35 @@ test "setAttribute and clearAttribute" { | |||
|     for (attrs) |attr| { | ||||
|         const old_val = val; | ||||
|         setAttribute(&val, attr); | ||||
|         std.testing.expectEqual(val, old_val | attr); | ||||
|         try std.testing.expectEqual(val, old_val | attr); | ||||
|     } | ||||
| 
 | ||||
|     for (attrs) |attr| { | ||||
|         const old_val = val; | ||||
|         clearAttribute(&val, attr); | ||||
|         std.testing.expectEqual(val, old_val & ~attr); | ||||
|         try std.testing.expectEqual(val, old_val & ~attr); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| test "virtToDirEntryIdx" { | ||||
|     expectEqual(virtToDirEntryIdx(0), 0); | ||||
|     expectEqual(virtToDirEntryIdx(123), 0); | ||||
|     expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB - 1), 0); | ||||
|     expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB), 1); | ||||
|     expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB + 1), 1); | ||||
|     expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB * 2), 2); | ||||
|     expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB * (ENTRIES_PER_DIRECTORY - 1)), ENTRIES_PER_DIRECTORY - 1); | ||||
|     try expectEqual(virtToDirEntryIdx(0), 0); | ||||
|     try expectEqual(virtToDirEntryIdx(123), 0); | ||||
|     try expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB - 1), 0); | ||||
|     try expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB), 1); | ||||
|     try expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB + 1), 1); | ||||
|     try expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB * 2), 2); | ||||
|     try expectEqual(virtToDirEntryIdx(PAGE_SIZE_4MB * (ENTRIES_PER_DIRECTORY - 1)), ENTRIES_PER_DIRECTORY - 1); | ||||
| } | ||||
| 
 | ||||
| test "virtToTableEntryIdx" { | ||||
|     expectEqual(virtToTableEntryIdx(0), 0); | ||||
|     expectEqual(virtToTableEntryIdx(123), 0); | ||||
|     expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB - 1), 0); | ||||
|     expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB), 1); | ||||
|     expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB + 1), 1); | ||||
|     expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB * 2), 2); | ||||
|     expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB * (ENTRIES_PER_TABLE - 1)), ENTRIES_PER_TABLE - 1); | ||||
|     expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB * (ENTRIES_PER_TABLE)), 0); | ||||
|     try expectEqual(virtToTableEntryIdx(0), 0); | ||||
|     try expectEqual(virtToTableEntryIdx(123), 0); | ||||
|     try expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB - 1), 0); | ||||
|     try expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB), 1); | ||||
|     try expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB + 1), 1); | ||||
|     try expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB * 2), 2); | ||||
|     try expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB * (ENTRIES_PER_TABLE - 1)), ENTRIES_PER_TABLE - 1); | ||||
|     try expectEqual(virtToTableEntryIdx(PAGE_SIZE_4KB * (ENTRIES_PER_TABLE)), 0); | ||||
| } | ||||
| 
 | ||||
| test "mapDirEntry" { | ||||
|  | @ -550,7 +551,7 @@ test "mapDirEntry" { | |||
|         const entry_idx = virtToDirEntryIdx(virt); | ||||
|         const entry = dir.entries[entry_idx]; | ||||
|         const table = dir.tables[entry_idx].?; | ||||
|         checkDirEntry(entry, virt, virt_end, phys, attrs, table, true); | ||||
|         try checkDirEntry(entry, virt, virt_end, phys, attrs, table, true); | ||||
|         const table_free = @ptrCast([*]Table, table)[0..1]; | ||||
|         allocator.free(table_free); | ||||
|     } | ||||
|  | @ -565,7 +566,7 @@ test "mapDirEntry" { | |||
|         const entry_idx = virtToDirEntryIdx(virt); | ||||
|         const entry = dir.entries[entry_idx]; | ||||
|         const table = dir.tables[entry_idx].?; | ||||
|         checkDirEntry(entry, virt, virt_end, phys, attrs, table, true); | ||||
|         try checkDirEntry(entry, virt, virt_end, phys, attrs, table, true); | ||||
|         const table_free = @ptrCast([*]Table, table)[0..1]; | ||||
|         allocator.free(table_free); | ||||
|     } | ||||
|  | @ -575,11 +576,11 @@ test "mapDirEntry returns errors correctly" { | |||
|     var allocator = std.testing.allocator; | ||||
|     var dir = Directory{ .entries = [_]DirectoryEntry{0} ** ENTRIES_PER_DIRECTORY, .tables = undefined }; | ||||
|     const attrs = vmm.Attributes{ .kernel = true, .writable = true, .cachable = true }; | ||||
|     testing.expectError(vmm.MapperError.MisalignedVirtualAddress, mapDirEntry(&dir, 1, PAGE_SIZE_4KB + 1, 0, PAGE_SIZE_4KB, attrs, allocator)); | ||||
|     testing.expectError(vmm.MapperError.MisalignedPhysicalAddress, mapDirEntry(&dir, 0, PAGE_SIZE_4KB, 1, PAGE_SIZE_4KB + 1, attrs, allocator)); | ||||
|     testing.expectError(vmm.MapperError.AddressMismatch, mapDirEntry(&dir, 0, PAGE_SIZE_4KB, 1, PAGE_SIZE_4KB, attrs, allocator)); | ||||
|     testing.expectError(vmm.MapperError.InvalidVirtualAddress, mapDirEntry(&dir, 1, 0, 0, PAGE_SIZE_4KB, attrs, allocator)); | ||||
|     testing.expectError(vmm.MapperError.InvalidPhysicalAddress, mapDirEntry(&dir, 0, PAGE_SIZE_4KB, 1, 0, attrs, allocator)); | ||||
|     try testing.expectError(vmm.MapperError.MisalignedVirtualAddress, mapDirEntry(&dir, 1, PAGE_SIZE_4KB + 1, 0, PAGE_SIZE_4KB, attrs, allocator)); | ||||
|     try testing.expectError(vmm.MapperError.MisalignedPhysicalAddress, mapDirEntry(&dir, 0, PAGE_SIZE_4KB, 1, PAGE_SIZE_4KB + 1, attrs, allocator)); | ||||
|     try testing.expectError(vmm.MapperError.AddressMismatch, mapDirEntry(&dir, 0, PAGE_SIZE_4KB, 1, PAGE_SIZE_4KB, attrs, allocator)); | ||||
|     try testing.expectError(vmm.MapperError.InvalidVirtualAddress, mapDirEntry(&dir, 1, 0, 0, PAGE_SIZE_4KB, attrs, allocator)); | ||||
|     try testing.expectError(vmm.MapperError.InvalidPhysicalAddress, mapDirEntry(&dir, 0, PAGE_SIZE_4KB, 1, 0, attrs, allocator)); | ||||
| } | ||||
| 
 | ||||
| test "map and unmap" { | ||||
|  | @ -605,7 +606,7 @@ test "map and unmap" { | |||
|         const entry_idx = virtToDirEntryIdx(virt); | ||||
|         const entry = dir.entries[entry_idx]; | ||||
|         const table = dir.tables[entry_idx].?; | ||||
|         checkDirEntry(entry, virt, virt + PAGE_SIZE_4MB, phys, attrs, table, true); | ||||
|         try checkDirEntry(entry, virt, virt + PAGE_SIZE_4MB, phys, attrs, table, true); | ||||
|     } | ||||
| 
 | ||||
|     try unmap(virt_start, virt_end, allocator, &dir); | ||||
|  | @ -618,7 +619,7 @@ test "map and unmap" { | |||
|         const entry_idx = virtToDirEntryIdx(virt); | ||||
|         const entry = dir.entries[entry_idx]; | ||||
|         const table = dir.tables[entry_idx].?; | ||||
|         checkDirEntry(entry, virt, virt + PAGE_SIZE_4MB, phys, attrs, table, false); | ||||
|         try checkDirEntry(entry, virt, virt + PAGE_SIZE_4MB, phys, attrs, table, false); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -634,12 +635,12 @@ test "copy" { | |||
|     var dir2 = dir.copy(); | ||||
|     const dir_slice = @ptrCast([*]const u8, &dir)[0..@sizeOf(Directory)]; | ||||
|     const dir2_slice = @ptrCast([*]const u8, &dir2)[0..@sizeOf(Directory)]; | ||||
|     testing.expectEqualSlices(u8, dir_slice, dir2_slice); | ||||
|     try testing.expectEqualSlices(u8, dir_slice, dir2_slice); | ||||
| 
 | ||||
|     // Changes to one should not affect the other | ||||
|     dir2.tables[1] = &table0; | ||||
|     dir.tables[0] = &table56; | ||||
|     testing.expect(!std.mem.eql(u8, dir_slice, dir2_slice)); | ||||
|     try expect(!std.mem.eql(u8, dir_slice, dir2_slice)); | ||||
| } | ||||
| 
 | ||||
| // The labels to jump to after attempting to cause a page fault. This is needed as we don't want to cause an | ||||
|  | @ -665,7 +666,7 @@ fn rt_accessUnmappedMem(v_end: u32) void { | |||
|     var ptr = @intToPtr(*u8, v_end); | ||||
|     var value = ptr.*; | ||||
|     // Need this as in release builds the above is optimised out so it needs to be use | ||||
|     log.emerg("FAILURE: Value: {}\n", .{value}); | ||||
|     log.err("FAILURE: Value: {}\n", .{value}); | ||||
|     // This is the label that we return to after processing the page fault | ||||
|     asm volatile ( | ||||
|         \\.global rt_fault_callback | ||||
|  | @ -682,7 +683,8 @@ fn rt_accessMappedMem(v_end: u32) void { | |||
|     faulted = false; | ||||
|     // Accessing mapped memory doesn't cause a page fault | ||||
|     var ptr = @intToPtr(*u8, v_end - PAGE_SIZE_4KB); | ||||
|     var value = ptr.*; | ||||
|     // Print the value to avoid the load from being optimised away | ||||
|     log.info("Read value in mapped memory: {}\n", .{ptr.*}); | ||||
|     asm volatile ( | ||||
|         \\.global rt_fault_callback2 | ||||
|         \\rt_fault_callback2: | ||||
|  |  | |||
|  | @ -3,11 +3,10 @@ const builtin = @import("builtin"); | |||
| const is_test = builtin.is_test; | ||||
| const expectEqual = std.testing.expectEqual; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const Allocator = std.mem.Allocator; | ||||
| const ArrayList = std.ArrayList; | ||||
| const log = std.log.scoped(.pci); | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| 
 | ||||
| /// The port address for selecting a 32bit register in the PCI configuration space. | ||||
| const CONFIG_ADDRESS: u16 = 0x0CF8; | ||||
|  | @ -161,7 +160,7 @@ const PciDevice = struct { | |||
| 
 | ||||
|             // RevisionId is a u8 width, offset 0 | ||||
|             const res = device.configReadData(2, .RevisionId); | ||||
|             expectEqual(res, 0x12); | ||||
|             try expectEqual(res, 0x12); | ||||
|         } | ||||
| 
 | ||||
|         { | ||||
|  | @ -175,7 +174,7 @@ const PciDevice = struct { | |||
| 
 | ||||
|             // ProgrammingInterface is a u8 width, offset 8 | ||||
|             const res = device.configReadData(2, .ProgrammingInterface); | ||||
|             expectEqual(res, 0xEF); | ||||
|             try expectEqual(res, 0xEF); | ||||
|         } | ||||
| 
 | ||||
|         { | ||||
|  | @ -189,7 +188,7 @@ const PciDevice = struct { | |||
| 
 | ||||
|             // Subclass is a u8 width, offset 16 | ||||
|             const res = device.configReadData(2, .Subclass); | ||||
|             expectEqual(res, 0xCD); | ||||
|             try expectEqual(res, 0xCD); | ||||
|         } | ||||
| 
 | ||||
|         { | ||||
|  | @ -203,7 +202,7 @@ const PciDevice = struct { | |||
| 
 | ||||
|             // ClassCode is a u8 width, offset 24 | ||||
|             const res = device.configReadData(2, .ClassCode); | ||||
|             expectEqual(res, 0xAB); | ||||
|             try expectEqual(res, 0xAB); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -226,7 +225,7 @@ const PciDevice = struct { | |||
| 
 | ||||
|             // VenderId is a u16 width, offset 0 | ||||
|             const res = device.configReadData(2, .VenderId); | ||||
|             expectEqual(res, 0xEF12); | ||||
|             try expectEqual(res, 0xEF12); | ||||
|         } | ||||
| 
 | ||||
|         { | ||||
|  | @ -240,7 +239,7 @@ const PciDevice = struct { | |||
| 
 | ||||
|             // DeviceId is a u16 width, offset 16 | ||||
|             const res = device.configReadData(2, .DeviceId); | ||||
|             expectEqual(res, 0xABCD); | ||||
|             try expectEqual(res, 0xABCD); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -263,7 +262,7 @@ const PciDevice = struct { | |||
| 
 | ||||
|             // BaseAddr0 is a u32 width, offset 0 | ||||
|             const res = device.configReadData(2, .BaseAddr0); | ||||
|             expectEqual(res, 0xABCDEF12); | ||||
|             try expectEqual(res, 0xABCDEF12); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | @ -317,7 +316,7 @@ pub const PciDeviceInfo = struct { | |||
| /// Get a list of all the PCI device. The returned list will needed to be freed by the caller. | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *Allocator - An allocator used for creating the list. | ||||
| ///     IN allocator: Allocator - An allocator used for creating the list. | ||||
| /// | ||||
| /// Return: []PciDeviceInfo | ||||
| ///     The list of PCI devices information. | ||||
|  | @ -325,7 +324,7 @@ pub const PciDeviceInfo = struct { | |||
| /// Error: Allocator.Error | ||||
| ///     error.OutOfMemory - If there isn't enough memory to create the info list. | ||||
| /// | ||||
| pub fn getDevices(allocator: *Allocator) Allocator.Error![]PciDeviceInfo { | ||||
| pub fn getDevices(allocator: Allocator) Allocator.Error![]PciDeviceInfo { | ||||
|     // Create an array list for the devices. | ||||
|     var pci_device_infos = ArrayList(PciDeviceInfo).init(allocator); | ||||
|     defer pci_device_infos.deinit(); | ||||
|  |  | |||
|  | @ -5,9 +5,8 @@ const log = std.log.scoped(.x86_pic); | |||
| const builtin = @import("builtin"); | ||||
| const is_test = builtin.is_test; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const panic = if (is_test) @import(mock_path ++ "panic_mock.zig").panic else @import("../../panic.zig").panic; | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| 
 | ||||
| // ---------- | ||||
| // Port address for the PIC master and slave registers. | ||||
|  | @ -251,7 +250,7 @@ var spurious_irq_counter: u32 = 0; | |||
| /// Arguments: | ||||
| ///     IN cmd: u8 - The command to send. | ||||
| /// | ||||
| fn sendCommandMaster(cmd: u8) callconv(.Inline) void { | ||||
| inline fn sendCommandMaster(cmd: u8) void { | ||||
|     arch.out(MASTER_COMMAND_REG, cmd); | ||||
| } | ||||
| 
 | ||||
|  | @ -261,7 +260,7 @@ fn sendCommandMaster(cmd: u8) callconv(.Inline) void { | |||
| /// Arguments: | ||||
| ///     IN cmd: u8 - The command to send. | ||||
| /// | ||||
| fn sendCommandSlave(cmd: u8) callconv(.Inline) void { | ||||
| inline fn sendCommandSlave(cmd: u8) void { | ||||
|     arch.out(SLAVE_COMMAND_REG, cmd); | ||||
| } | ||||
| 
 | ||||
|  | @ -271,7 +270,7 @@ fn sendCommandSlave(cmd: u8) callconv(.Inline) void { | |||
| /// Arguments: | ||||
| ///     IN data: u8 - The data to send. | ||||
| /// | ||||
| fn sendDataMaster(data: u8) callconv(.Inline) void { | ||||
| inline fn sendDataMaster(data: u8) void { | ||||
|     arch.out(MASTER_DATA_REG, data); | ||||
| } | ||||
| 
 | ||||
|  | @ -281,7 +280,7 @@ fn sendDataMaster(data: u8) callconv(.Inline) void { | |||
| /// Arguments: | ||||
| ///     IN data: u8 - The data to send. | ||||
| /// | ||||
| fn sendDataSlave(data: u8) callconv(.Inline) void { | ||||
| inline fn sendDataSlave(data: u8) void { | ||||
|     arch.out(SLAVE_DATA_REG, data); | ||||
| } | ||||
| 
 | ||||
|  | @ -291,7 +290,7 @@ fn sendDataSlave(data: u8) callconv(.Inline) void { | |||
| /// Return: u8 | ||||
| ///     The data that is stored in the master data register. | ||||
| /// | ||||
| fn readDataMaster() callconv(.Inline) u8 { | ||||
| inline fn readDataMaster() u8 { | ||||
|     return arch.in(u8, MASTER_DATA_REG); | ||||
| } | ||||
| 
 | ||||
|  | @ -301,7 +300,7 @@ fn readDataMaster() callconv(.Inline) u8 { | |||
| /// Return: u8 | ||||
| ///     The data that is stored in the salve data register. | ||||
| /// | ||||
| fn readDataSlave() callconv(.Inline) u8 { | ||||
| inline fn readDataSlave() u8 { | ||||
|     return arch.in(u8, SLAVE_DATA_REG); | ||||
| } | ||||
| 
 | ||||
|  | @ -311,7 +310,7 @@ fn readDataSlave() callconv(.Inline) u8 { | |||
| /// Return: u8 | ||||
| ///     The data that is stored in the master IRR. | ||||
| /// | ||||
| fn readMasterIrr() callconv(.Inline) u8 { | ||||
| inline fn readMasterIrr() u8 { | ||||
|     sendCommandMaster(OCW3_DEFAULT | OCW3_ACT_ON_READ | OCW3_READ_IRR); | ||||
|     return arch.in(u8, MASTER_STATUS_REG); | ||||
| } | ||||
|  | @ -322,7 +321,7 @@ fn readMasterIrr() callconv(.Inline) u8 { | |||
| /// Return: u8 | ||||
| ///     The data that is stored in the slave IRR. | ||||
| /// | ||||
| fn readSlaveIrr() callconv(.Inline) u8 { | ||||
| inline fn readSlaveIrr() u8 { | ||||
|     sendCommandSlave(OCW3_DEFAULT | OCW3_ACT_ON_READ | OCW3_READ_IRR); | ||||
|     return arch.in(u8, SLAVE_STATUS_REG); | ||||
| } | ||||
|  | @ -333,7 +332,7 @@ fn readSlaveIrr() callconv(.Inline) u8 { | |||
| /// Return: u8 | ||||
| ///     The data that is stored in the master ISR. | ||||
| /// | ||||
| fn readMasterIsr() callconv(.Inline) u8 { | ||||
| inline fn readMasterIsr() u8 { | ||||
|     sendCommandMaster(OCW3_DEFAULT | OCW3_ACT_ON_READ | OCW3_READ_ISR); | ||||
|     return arch.in(u8, MASTER_STATUS_REG); | ||||
| } | ||||
|  | @ -344,7 +343,7 @@ fn readMasterIsr() callconv(.Inline) u8 { | |||
| /// Return: u8 | ||||
| ///     The data that is stored in the slave ISR. | ||||
| /// | ||||
| fn readSlaveIsr() callconv(.Inline) u8 { | ||||
| inline fn readSlaveIsr() u8 { | ||||
|     sendCommandSlave(OCW3_DEFAULT | OCW3_ACT_ON_READ | OCW3_READ_ISR); | ||||
|     return arch.in(u8, SLAVE_STATUS_REG); | ||||
| } | ||||
|  | @ -529,7 +528,7 @@ test "readDataMaster" { | |||
| 
 | ||||
|     arch.addTestParams("in", .{ MASTER_DATA_REG, @as(u8, 10) }); | ||||
| 
 | ||||
|     expectEqual(@as(u8, 10), readDataMaster()); | ||||
|     try expectEqual(@as(u8, 10), readDataMaster()); | ||||
| } | ||||
| 
 | ||||
| test "readDataSlave" { | ||||
|  | @ -539,7 +538,7 @@ test "readDataSlave" { | |||
| 
 | ||||
|     arch.addTestParams("in", .{ SLAVE_DATA_REG, @as(u8, 10) }); | ||||
| 
 | ||||
|     expectEqual(@as(u8, 10), readDataSlave()); | ||||
|     try expectEqual(@as(u8, 10), readDataSlave()); | ||||
| } | ||||
| 
 | ||||
| test "readMasterIrr" { | ||||
|  | @ -550,7 +549,7 @@ test "readMasterIrr" { | |||
|     arch.addTestParams("out", .{ MASTER_COMMAND_REG, @as(u8, 0x0A) }); | ||||
|     arch.addTestParams("in", .{ MASTER_STATUS_REG, @as(u8, 10) }); | ||||
| 
 | ||||
|     expectEqual(@as(u8, 10), readMasterIrr()); | ||||
|     try expectEqual(@as(u8, 10), readMasterIrr()); | ||||
| } | ||||
| 
 | ||||
| test "readSlaveIrr" { | ||||
|  | @ -561,7 +560,7 @@ test "readSlaveIrr" { | |||
|     arch.addTestParams("out", .{ SLAVE_COMMAND_REG, @as(u8, 0x0A) }); | ||||
|     arch.addTestParams("in", .{ SLAVE_STATUS_REG, @as(u8, 10) }); | ||||
| 
 | ||||
|     expectEqual(@as(u8, 10), readSlaveIrr()); | ||||
|     try expectEqual(@as(u8, 10), readSlaveIrr()); | ||||
| } | ||||
| 
 | ||||
| test "readMasterIsr" { | ||||
|  | @ -572,7 +571,7 @@ test "readMasterIsr" { | |||
|     arch.addTestParams("out", .{ MASTER_COMMAND_REG, @as(u8, 0x0B) }); | ||||
|     arch.addTestParams("in", .{ MASTER_STATUS_REG, @as(u8, 10) }); | ||||
| 
 | ||||
|     expectEqual(@as(u8, 10), readMasterIsr()); | ||||
|     try expectEqual(@as(u8, 10), readMasterIsr()); | ||||
| } | ||||
| 
 | ||||
| test "readSlaveIsr" { | ||||
|  | @ -583,7 +582,7 @@ test "readSlaveIsr" { | |||
|     arch.addTestParams("out", .{ SLAVE_COMMAND_REG, @as(u8, 0x0B) }); | ||||
|     arch.addTestParams("in", .{ SLAVE_STATUS_REG, @as(u8, 10) }); | ||||
| 
 | ||||
|     expectEqual(@as(u8, 10), readSlaveIsr()); | ||||
|     try expectEqual(@as(u8, 10), readSlaveIsr()); | ||||
| } | ||||
| 
 | ||||
| test "sendEndOfInterrupt master only" { | ||||
|  | @ -615,17 +614,17 @@ test "sendEndOfInterrupt master and slave" { | |||
| 
 | ||||
| test "spuriousIrq not spurious IRQ number" { | ||||
|     // Pre testing | ||||
|     expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
| 
 | ||||
|     var i: u8 = 0; | ||||
|     while (i < 16) : (i += 1) { | ||||
|         if (i != 7 and i != 15) { | ||||
|             expectEqual(false, spuriousIrq(i)); | ||||
|             try expectEqual(false, spuriousIrq(i)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Post testing | ||||
|     expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
| 
 | ||||
|     // Clean up | ||||
|     spurious_irq_counter = 0; | ||||
|  | @ -641,13 +640,13 @@ test "spuriousIrq spurious master IRQ number not spurious" { | |||
|     arch.addTestParams("in", .{ MASTER_STATUS_REG, @as(u8, 0x80) }); | ||||
| 
 | ||||
|     // Pre testing | ||||
|     expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
| 
 | ||||
|     // Call function | ||||
|     expectEqual(false, spuriousIrq(7)); | ||||
|     try expectEqual(false, spuriousIrq(7)); | ||||
| 
 | ||||
|     // Post testing | ||||
|     expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
| 
 | ||||
|     // Clean up | ||||
|     spurious_irq_counter = 0; | ||||
|  | @ -663,13 +662,13 @@ test "spuriousIrq spurious master IRQ number spurious" { | |||
|     arch.addTestParams("in", .{ MASTER_STATUS_REG, @as(u8, 0x0) }); | ||||
| 
 | ||||
|     // Pre testing | ||||
|     expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
| 
 | ||||
|     // Call function | ||||
|     expectEqual(true, spuriousIrq(7)); | ||||
|     try expectEqual(true, spuriousIrq(7)); | ||||
| 
 | ||||
|     // Post testing | ||||
|     expectEqual(@as(u32, 1), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 1), spurious_irq_counter); | ||||
| 
 | ||||
|     // Clean up | ||||
|     spurious_irq_counter = 0; | ||||
|  | @ -685,13 +684,13 @@ test "spuriousIrq spurious slave IRQ number not spurious" { | |||
|     arch.addTestParams("in", .{ SLAVE_STATUS_REG, @as(u8, 0x80) }); | ||||
| 
 | ||||
|     // Pre testing | ||||
|     expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
| 
 | ||||
|     // Call function | ||||
|     expectEqual(false, spuriousIrq(15)); | ||||
|     try expectEqual(false, spuriousIrq(15)); | ||||
| 
 | ||||
|     // Post testing | ||||
|     expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
| 
 | ||||
|     // Clean up | ||||
|     spurious_irq_counter = 0; | ||||
|  | @ -709,13 +708,13 @@ test "spuriousIrq spurious slave IRQ number spurious" { | |||
|     arch.addTestParams("out", .{ MASTER_COMMAND_REG, OCW2_END_OF_INTERRUPT }); | ||||
| 
 | ||||
|     // Pre testing | ||||
|     expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 0), spurious_irq_counter); | ||||
| 
 | ||||
|     // Call function | ||||
|     expectEqual(true, spuriousIrq(15)); | ||||
|     try expectEqual(true, spuriousIrq(15)); | ||||
| 
 | ||||
|     // Post testing | ||||
|     expectEqual(@as(u32, 1), spurious_irq_counter); | ||||
|     try expectEqual(@as(u32, 1), spurious_irq_counter); | ||||
| 
 | ||||
|     // Clean up | ||||
|     spurious_irq_counter = 0; | ||||
|  |  | |||
|  | @ -7,8 +7,7 @@ const expectEqual = std.testing.expectEqual; | |||
| const expectError = std.testing.expectError; | ||||
| const log = std.log.scoped(.x86_pit); | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| const irq = @import("irq.zig"); | ||||
| const pic = @import("pic.zig"); | ||||
|  | @ -198,7 +197,7 @@ var time_under_1_ns: u32 = undefined; | |||
| /// Arguments: | ||||
| ///     IN cmd: u8 - The command to send to the PIT. | ||||
| /// | ||||
| fn sendCommand(cmd: u8) callconv(.Inline) void { | ||||
| inline fn sendCommand(cmd: u8) void { | ||||
|     arch.out(COMMAND_REGISTER, cmd); | ||||
| } | ||||
| 
 | ||||
|  | @ -211,7 +210,7 @@ fn sendCommand(cmd: u8) callconv(.Inline) void { | |||
| /// Return: u8 | ||||
| ///     The mode the counter is operating in. Use the masks above to get each part. | ||||
| /// | ||||
| fn readBackCommand(counter: CounterSelect) callconv(.Inline) u8 { | ||||
| inline fn readBackCommand(counter: CounterSelect) u8 { | ||||
|     sendCommand(0xC2); | ||||
|     return 0x3F & arch.in(u8, counter.getRegister()); | ||||
| } | ||||
|  | @ -223,7 +222,7 @@ fn readBackCommand(counter: CounterSelect) callconv(.Inline) u8 { | |||
| ///     IN counter: CounterSelect - The counter port to send the data to. | ||||
| ///     IN data: u8               - The data to send. | ||||
| /// | ||||
| fn sendDataToCounter(counter: CounterSelect, data: u8) callconv(.Inline) void { | ||||
| inline fn sendDataToCounter(counter: CounterSelect, data: u8) void { | ||||
|     arch.out(counter.getRegister(), data); | ||||
| } | ||||
| 
 | ||||
|  | @ -368,7 +367,7 @@ pub fn init() void { | |||
| 
 | ||||
|     // Set up counter 0 at 10000hz in a square wave mode counting in binary | ||||
|     const freq: u32 = 10000; | ||||
|     setupCounter(CounterSelect.Counter0, freq, OCW_MODE_SQUARE_WAVE_GENERATOR | OCW_BINARY_COUNT_BINARY) catch |e| { | ||||
|     setupCounter(CounterSelect.Counter0, freq, OCW_MODE_SQUARE_WAVE_GENERATOR | OCW_BINARY_COUNT_BINARY) catch { | ||||
|         panic(@errorReturnTrace(), "Invalid frequency: {}\n", .{freq}); | ||||
|     }; | ||||
| 
 | ||||
|  | @ -412,7 +411,7 @@ test "readBackCommand" { | |||
| 
 | ||||
|     const actual = readBackCommand(CounterSelect.Counter0); | ||||
| 
 | ||||
|     expectEqual(@as(u8, 0x20), actual); | ||||
|     try expectEqual(@as(u8, 0x20), actual); | ||||
| } | ||||
| 
 | ||||
| test "sendDataToCounter" { | ||||
|  | @ -431,36 +430,14 @@ test "setupCounter lowest frequency" { | |||
|     defer arch.freeTest(); | ||||
| 
 | ||||
|     const counter = CounterSelect.Counter0; | ||||
|     const port = counter.getRegister(); | ||||
| 
 | ||||
|     var freq: u32 = 0; | ||||
| 
 | ||||
|     // Reload value will be 0 (0x10000), the slowest speed for frequency less than 19 | ||||
|     const expected_reload_value: u16 = 0; | ||||
| 
 | ||||
|     // Slowest frequency the PIT can run at | ||||
|     const expected_freq: u32 = 19; | ||||
| 
 | ||||
|     const mode = OCW_MODE_SQUARE_WAVE_GENERATOR | OCW_BINARY_COUNT_BINARY; | ||||
|     const command = mode | OCW_READ_LOAD_DATA | counter.getCounterOCW(); | ||||
| 
 | ||||
|     while (freq <= 18) : (freq += 1) { | ||||
|         // arch.addTestParams("out", COMMAND_REGISTER, command, port, @truncate(u8, expected_reload_value), port, @truncate(u8, expected_reload_value >> 8)); | ||||
|         expectError(PitError.InvalidFrequency, setupCounter(counter, freq, mode)); | ||||
| 
 | ||||
|         // expectEqual(u32(0), ticks); | ||||
|         // expectEqual(expected_freq, current_freq_0); | ||||
|         // expectEqual(expected_freq, getFrequency()); | ||||
| 
 | ||||
|         // // These are the hard coded expected values. Calculated externally to check the internal calculation | ||||
|         // expectEqual(u32(52631578), time_ns); | ||||
|         // expectEqual(u32(947), time_under_1_ns); | ||||
|         try expectError(PitError.InvalidFrequency, setupCounter(counter, freq, mode)); | ||||
|     } | ||||
| 
 | ||||
|     // Reset globals | ||||
|     time_ns = 0; | ||||
|     current_freq_0 = 0; | ||||
|     ticks = 0; | ||||
| } | ||||
| 
 | ||||
| test "setupCounter highest frequency" { | ||||
|  | @ -468,36 +445,13 @@ test "setupCounter highest frequency" { | |||
|     defer arch.freeTest(); | ||||
| 
 | ||||
|     const counter = CounterSelect.Counter0; | ||||
|     const port = counter.getRegister(); | ||||
| 
 | ||||
|     // Set the frequency above the maximum | ||||
|     const freq = MAX_FREQUENCY + 10; | ||||
| 
 | ||||
|     // Reload value will be 1, the fastest speed for frequency greater than MAX_FREQUENCY | ||||
|     const expected_reload_value = 1; | ||||
| 
 | ||||
|     // Slowest frequency the PIT can run at | ||||
|     const expected_freq = MAX_FREQUENCY; | ||||
| 
 | ||||
|     const mode = OCW_MODE_SQUARE_WAVE_GENERATOR | OCW_BINARY_COUNT_BINARY; | ||||
|     const command = mode | OCW_READ_LOAD_DATA | counter.getCounterOCW(); | ||||
| 
 | ||||
|     // arch.addTestParams("out", COMMAND_REGISTER, command, port, @truncate(u8, expected_reload_value), port, @truncate(u8, expected_reload_value >> 8)); | ||||
| 
 | ||||
|     expectError(PitError.InvalidFrequency, setupCounter(counter, freq, mode)); | ||||
| 
 | ||||
|     // expectEqual(u32(0), ticks); | ||||
|     // expectEqual(expected_freq, current_freq_0); | ||||
|     // expectEqual(expected_freq, getFrequency()); | ||||
| 
 | ||||
|     // // These are the hard coded expected values. Calculated externally to check the internal calculation | ||||
|     // expectEqual(u32(838), time_ns); | ||||
|     // expectEqual(u32(95), time_under_1_ns); | ||||
| 
 | ||||
|     // Reset globals | ||||
|     time_ns = 0; | ||||
|     current_freq_0 = 0; | ||||
|     ticks = 0; | ||||
|     try expectError(PitError.InvalidFrequency, setupCounter(counter, freq, mode)); | ||||
| } | ||||
| 
 | ||||
| test "setupCounter normal frequency" { | ||||
|  | @ -519,13 +473,13 @@ test "setupCounter normal frequency" { | |||
| 
 | ||||
|     setupCounter(counter, freq, mode) catch unreachable; | ||||
| 
 | ||||
|     expectEqual(@as(u32, 0), ticks); | ||||
|     expectEqual(expected_freq, current_freq_0); | ||||
|     expectEqual(expected_freq, getFrequency()); | ||||
|     try expectEqual(@as(u32, 0), ticks); | ||||
|     try expectEqual(expected_freq, current_freq_0); | ||||
|     try expectEqual(expected_freq, getFrequency()); | ||||
| 
 | ||||
|     // These are the hard coded expected values. Calculated externally to check the internal calculation | ||||
|     expectEqual(@as(u32, 99730), time_ns); | ||||
|     expectEqual(@as(u32, 727), time_under_1_ns); | ||||
|     try expectEqual(@as(u32, 99730), time_ns); | ||||
|     try expectEqual(@as(u32, 727), time_under_1_ns); | ||||
| 
 | ||||
|     // Reset globals | ||||
|     time_ns = 0; | ||||
|  |  | |||
|  | @ -6,12 +6,11 @@ const expectEqual = std.testing.expectEqual; | |||
| const expectError = std.testing.expectError; | ||||
| const log = std.log.scoped(.x86_rtc); | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const pic = @import("pic.zig"); | ||||
| const pit = @import("pit.zig"); | ||||
| const irq = @import("irq.zig"); | ||||
| const cmos = if (is_test) @import(mock_path ++ "cmos_mock.zig") else @import("cmos.zig"); | ||||
| const cmos = if (is_test) @import("../../../../test/mock/kernel/cmos_mock.zig") else @import("cmos.zig"); | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| const scheduler = @import("../../scheduler.zig"); | ||||
| 
 | ||||
|  | @ -166,7 +165,7 @@ fn rtcHandler(ctx: *arch.CpuState) usize { | |||
| 
 | ||||
|     // Need to read status register C | ||||
|     // Might need to disable the NMI bit, set to true | ||||
|     const reg_c = cmos.readStatusRegister(cmos.StatusRegister.C, false); | ||||
|     _ = cmos.readStatusRegister(cmos.StatusRegister.C, false); | ||||
| 
 | ||||
|     return ret_esp; | ||||
| } | ||||
|  | @ -290,7 +289,7 @@ pub fn init() void { | |||
|     enableInterrupts(); | ||||
| 
 | ||||
|     // Read status register C to clear any interrupts that may have happened during set up | ||||
|     const reg_c = cmos.readStatusRegister(cmos.StatusRegister.C, false); | ||||
|     _ = cmos.readStatusRegister(cmos.StatusRegister.C, false); | ||||
| 
 | ||||
|     switch (build_options.test_mode) { | ||||
|         .Initialisation => runtimeTests(), | ||||
|  | @ -307,7 +306,7 @@ test "isBusy not busy" { | |||
|         .{ cmos.StatusRegister.A, false, @as(u8, 0x60) }, | ||||
|     ); | ||||
| 
 | ||||
|     expect(!isBusy()); | ||||
|     try expect(!isBusy()); | ||||
| } | ||||
| 
 | ||||
| test "isBusy busy" { | ||||
|  | @ -319,7 +318,7 @@ test "isBusy busy" { | |||
|         .{ cmos.StatusRegister.A, false, @as(u8, 0x80) }, | ||||
|     ); | ||||
| 
 | ||||
|     expect(isBusy()); | ||||
|     try expect(isBusy()); | ||||
| } | ||||
| 
 | ||||
| test "calcDayOfWeek" { | ||||
|  | @ -337,7 +336,7 @@ test "calcDayOfWeek" { | |||
|     var actual = calcDayOfWeek(date_time); | ||||
|     var expected = @as(u32, 5); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| 
 | ||||
|     date_time.day = 20; | ||||
|     date_time.month = 7; | ||||
|  | @ -346,7 +345,7 @@ test "calcDayOfWeek" { | |||
|     actual = calcDayOfWeek(date_time); | ||||
|     expected = @as(u32, 6); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| 
 | ||||
|     date_time.day = 9; | ||||
|     date_time.month = 11; | ||||
|  | @ -355,7 +354,7 @@ test "calcDayOfWeek" { | |||
|     actual = calcDayOfWeek(date_time); | ||||
|     expected = @as(u32, 1); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| 
 | ||||
|     date_time.day = 1; | ||||
|     date_time.month = 1; | ||||
|  | @ -364,7 +363,7 @@ test "calcDayOfWeek" { | |||
|     actual = calcDayOfWeek(date_time); | ||||
|     expected = @as(u32, 6); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "isBcd not BCD" { | ||||
|  | @ -376,7 +375,7 @@ test "isBcd not BCD" { | |||
|         .{ cmos.StatusRegister.B, false, @as(u8, 0x00) }, | ||||
|     ); | ||||
| 
 | ||||
|     expect(!isBcd()); | ||||
|     try expect(!isBcd()); | ||||
| } | ||||
| 
 | ||||
| test "isBcd BCD" { | ||||
|  | @ -388,7 +387,7 @@ test "isBcd BCD" { | |||
|         .{ cmos.StatusRegister.B, false, @as(u8, 0x04) }, | ||||
|     ); | ||||
| 
 | ||||
|     expect(isBcd()); | ||||
|     try expect(isBcd()); | ||||
| } | ||||
| 
 | ||||
| test "is12Hr not 12Hr" { | ||||
|  | @ -411,7 +410,7 @@ test "is12Hr not 12Hr" { | |||
|         .{ cmos.StatusRegister.B, false, @as(u8, 0x00) }, | ||||
|     ); | ||||
| 
 | ||||
|     expect(!is12Hr(date_time)); | ||||
|     try expect(!is12Hr(date_time)); | ||||
| } | ||||
| 
 | ||||
| test "is12Hr 12Hr" { | ||||
|  | @ -434,24 +433,24 @@ test "is12Hr 12Hr" { | |||
|         .{ cmos.StatusRegister.B, false, @as(u8, 0x02) }, | ||||
|     ); | ||||
| 
 | ||||
|     expect(is12Hr(date_time)); | ||||
|     try expect(is12Hr(date_time)); | ||||
| } | ||||
| 
 | ||||
| test "bcdToBinary" { | ||||
|     var expected = @as(u32, 59); | ||||
|     var actual = bcdToBinary(0x59); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| 
 | ||||
|     expected = @as(u32, 48); | ||||
|     actual = bcdToBinary(0x48); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| 
 | ||||
|     expected = @as(u32, 1); | ||||
|     actual = bcdToBinary(0x01); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "readRtcRegisters" { | ||||
|  | @ -486,7 +485,7 @@ test "readRtcRegisters" { | |||
|     }; | ||||
|     const actual = readRtcRegisters(); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "readRtc unstable read" { | ||||
|  | @ -560,7 +559,7 @@ test "readRtc unstable read" { | |||
|     }; | ||||
|     const actual = getDateTime(); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "readRtc is BCD" { | ||||
|  | @ -613,7 +612,7 @@ test "readRtc is BCD" { | |||
|     }; | ||||
|     const actual = getDateTime(); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "readRtc is 12 hours" { | ||||
|  | @ -666,13 +665,13 @@ test "readRtc is 12 hours" { | |||
|     }; | ||||
|     const actual = getDateTime(); | ||||
| 
 | ||||
|     expectEqual(expected, actual); | ||||
|     try expectEqual(expected, actual); | ||||
| } | ||||
| 
 | ||||
| test "setRate below 3" { | ||||
|     expectError(RtcError.RateError, setRate(0)); | ||||
|     expectError(RtcError.RateError, setRate(1)); | ||||
|     expectError(RtcError.RateError, setRate(2)); | ||||
|     try expectError(RtcError.RateError, setRate(0)); | ||||
|     try expectError(RtcError.RateError, setRate(1)); | ||||
|     try expectError(RtcError.RateError, setRate(2)); | ||||
| } | ||||
| 
 | ||||
| test "setRate" { | ||||
|  |  | |||
|  | @ -151,21 +151,21 @@ test "lcrValue computes the correct value" { | |||
|                         @boolToInt(stop_bit) << 2 | | ||||
|                         @boolToInt(parity_bit) << 3 | | ||||
|                         @intCast(u8, msb) << 7; | ||||
|                     testing.expectEqual(val, expected); | ||||
|                     try testing.expectEqual(val, expected); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Check invalid char lengths | ||||
|     testing.expectError(SerialError.InvalidCharacterLength, lcrValue(4, false, false, 0)); | ||||
|     testing.expectError(SerialError.InvalidCharacterLength, lcrValue(9, false, false, 0)); | ||||
|     try testing.expectError(SerialError.InvalidCharacterLength, lcrValue(4, false, false, 0)); | ||||
|     try testing.expectError(SerialError.InvalidCharacterLength, lcrValue(9, false, false, 0)); | ||||
| } | ||||
| 
 | ||||
| test "baudDivisor" { | ||||
|     // Check invalid baudrates | ||||
|     inline for ([_]u32{ 0, BAUD_MAX + 1 }) |baud| { | ||||
|         testing.expectError(SerialError.InvalidBaudRate, baudDivisor(baud)); | ||||
|         try testing.expectError(SerialError.InvalidBaudRate, baudDivisor(baud)); | ||||
|     } | ||||
| 
 | ||||
|     // Check valid baudrates | ||||
|  | @ -173,6 +173,6 @@ test "baudDivisor" { | |||
|     while (baud <= BAUD_MAX) : (baud += 1) { | ||||
|         const val = try baudDivisor(baud); | ||||
|         const expected = @truncate(u16, BAUD_MAX / baud); | ||||
|         testing.expectEqual(val, expected); | ||||
|         try testing.expectEqual(val, expected); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -3,8 +3,7 @@ const log = std.log.scoped(.x86_syscalls); | |||
| const builtin = @import("builtin"); | ||||
| const is_test = builtin.is_test; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.arch_mock_path; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const testing = std.testing; | ||||
| const expect = std.testing.expect; | ||||
| const isr = @import("isr.zig"); | ||||
|  | @ -18,7 +17,7 @@ pub const INTERRUPT: u16 = 0x80; | |||
| pub const NUM_HANDLERS: u16 = 256; | ||||
| 
 | ||||
| /// A syscall handler | ||||
| pub const Handler = fn (ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize; | ||||
| pub const Handler = fn (arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize; | ||||
| 
 | ||||
| /// Errors that syscall utility functions can throw | ||||
| pub const Error = error{ | ||||
|  | @ -65,7 +64,7 @@ fn handle(ctx: *arch.CpuState) usize { | |||
|     const syscall = ctx.eax; | ||||
|     if (isValidSyscall(syscall)) { | ||||
|         if (handlers[syscall]) |handler| { | ||||
|             const result = handler(ctx, syscallArg(ctx, 0), syscallArg(ctx, 1), syscallArg(ctx, 2), syscallArg(ctx, 3), syscallArg(ctx, 4)); | ||||
|             const result = handler(syscallArg(ctx, 0), syscallArg(ctx, 1), syscallArg(ctx, 2), syscallArg(ctx, 3), syscallArg(ctx, 4)); | ||||
|             if (result) |res| { | ||||
|                 ctx.eax = res; | ||||
|                 ctx.ebx = 0; | ||||
|  | @ -112,15 +111,15 @@ pub fn registerSyscall(syscall: usize, handler: Handler) Error!void { | |||
| /// Error: syscalls.Error | ||||
| ///     This function will return the error that the syscall handler returns. See the documentation for the syscall for details. | ||||
| /// | ||||
| fn syscall0(syscall: usize) callconv(.Inline) syscalls.Error!usize { | ||||
| inline fn syscall0(syscall: usize) syscalls.Error!usize { | ||||
|     const res = asm volatile ( | ||||
|         \\int $0x80 | ||||
|         : [ret] "={eax}" (-> usize) | ||||
|         : [syscall] "{eax}" (syscall) | ||||
|         : [ret] "={eax}" (-> usize), | ||||
|         : [syscall] "{eax}" (syscall), | ||||
|         : "ebx" | ||||
|     ); | ||||
|     const err = asm ("" | ||||
|         : [ret] "={ebx}" (-> usize) | ||||
|         : [ret] "={ebx}" (-> usize), | ||||
|     ); | ||||
|     if (err != 0) { | ||||
|         return syscalls.fromErrorCode(err); | ||||
|  | @ -141,15 +140,15 @@ fn syscall0(syscall: usize) callconv(.Inline) syscalls.Error!usize { | |||
| /// Error: syscalls.Error | ||||
| ///     This function will return the error that the syscall handler returns. See the documentation for the syscall for details. | ||||
| /// | ||||
| fn syscall1(syscall: usize, arg: usize) callconv(.Inline) syscalls.Error!usize { | ||||
| inline fn syscall1(syscall: usize, arg: usize) syscalls.Error!usize { | ||||
|     const res = asm volatile ( | ||||
|         \\int $0x80 | ||||
|         : [ret] "={eax}" (-> usize) | ||||
|         : [ret] "={eax}" (-> usize), | ||||
|         : [syscall] "{eax}" (syscall), | ||||
|           [arg1] "{ebx}" (arg) | ||||
|           [arg1] "{ebx}" (arg), | ||||
|     ); | ||||
|     const err = asm ("" | ||||
|         : [ret] "={ebx}" (-> usize) | ||||
|         : [ret] "={ebx}" (-> usize), | ||||
|     ); | ||||
|     if (err != 0) { | ||||
|         return syscalls.fromErrorCode(err); | ||||
|  | @ -171,16 +170,16 @@ fn syscall1(syscall: usize, arg: usize) callconv(.Inline) syscalls.Error!usize { | |||
| /// Error: syscalls.Error | ||||
| ///     This function will return the error that the syscall handler returns. See the documentation for the syscall for details. | ||||
| /// | ||||
| fn syscall2(syscall: usize, arg1: usize, arg2: usize) callconv(.Inline) syscalls.Error!usize { | ||||
| inline fn syscall2(syscall: usize, arg1: usize, arg2: usize) syscalls.Error!usize { | ||||
|     const res = asm volatile ( | ||||
|         \\int $0x80 | ||||
|         : [ret] "={eax}" (-> usize) | ||||
|         : [ret] "={eax}" (-> usize), | ||||
|         : [syscall] "{eax}" (syscall), | ||||
|           [arg1] "{ebx}" (arg1), | ||||
|           [arg2] "{ecx}" (arg2) | ||||
|           [arg2] "{ecx}" (arg2), | ||||
|     ); | ||||
|     const err = asm ("" | ||||
|         : [ret] "={ebx}" (-> usize) | ||||
|         : [ret] "={ebx}" (-> usize), | ||||
|     ); | ||||
|     if (err != 0) { | ||||
|         return syscalls.fromErrorCode(err); | ||||
|  | @ -203,17 +202,17 @@ fn syscall2(syscall: usize, arg1: usize, arg2: usize) callconv(.Inline) syscalls | |||
| /// Error: syscalls.Error | ||||
| ///     This function will return the error that the syscall handler returns. See the documentation for the syscall for details. | ||||
| /// | ||||
| fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) callconv(.Inline) syscalls.Error!usize { | ||||
| inline fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) syscalls.Error!usize { | ||||
|     const res = asm volatile ( | ||||
|         \\int $0x80 | ||||
|         : [ret] "={eax}" (-> usize) | ||||
|         : [ret] "={eax}" (-> usize), | ||||
|         : [syscall] "{eax}" (syscall), | ||||
|           [arg1] "{ebx}" (arg1), | ||||
|           [arg2] "{ecx}" (arg2), | ||||
|           [arg3] "{edx}" (arg3) | ||||
|           [arg3] "{edx}" (arg3), | ||||
|     ); | ||||
|     const err = asm ("" | ||||
|         : [ret] "={ebx}" (-> usize) | ||||
|         : [ret] "={ebx}" (-> usize), | ||||
|     ); | ||||
|     if (err != 0) { | ||||
|         return syscalls.fromErrorCode(err); | ||||
|  | @ -237,18 +236,18 @@ fn syscall3(syscall: usize, arg1: usize, arg2: usize, arg3: usize) callconv(.Inl | |||
| /// Error: syscalls.Error | ||||
| ///     This function will return the error that the syscall handler returns. See the documentation for the syscall for details. | ||||
| /// | ||||
| fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) callconv(.Inline) syscalls.Error!usize { | ||||
| inline fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) syscalls.Error!usize { | ||||
|     const res = asm volatile ( | ||||
|         \\int $0x80 | ||||
|         : [ret] "={eax}" (-> usize) | ||||
|         : [ret] "={eax}" (-> usize), | ||||
|         : [syscall] "{eax}" (syscall), | ||||
|           [arg1] "{ebx}" (arg1), | ||||
|           [arg2] "{ecx}" (arg2), | ||||
|           [arg3] "{edx}" (arg3), | ||||
|           [arg4] "{esi}" (arg4) | ||||
|           [arg4] "{esi}" (arg4), | ||||
|     ); | ||||
|     const err = asm ("" | ||||
|         : [ret] "={ebx}" (-> usize) | ||||
|         : [ret] "={ebx}" (-> usize), | ||||
|     ); | ||||
|     if (err != 0) { | ||||
|         return syscalls.fromErrorCode(err); | ||||
|  | @ -273,19 +272,19 @@ fn syscall4(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) | |||
| /// Error: syscalls.Error | ||||
| ///     This function will return the error that the syscall handler returns. See the documentation for the syscall for details. | ||||
| /// | ||||
| fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) callconv(.Inline) syscalls.Error!usize { | ||||
| inline fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|     const res = asm volatile ( | ||||
|         \\int $0x80 | ||||
|         : [ret] "={eax}" (-> usize) | ||||
|         : [ret] "={eax}" (-> usize), | ||||
|         : [syscall] "{eax}" (syscall), | ||||
|           [arg1] "{ebx}" (arg1), | ||||
|           [arg2] "{ecx}" (arg2), | ||||
|           [arg3] "{edx}" (arg3), | ||||
|           [arg4] "{esi}" (arg4), | ||||
|           [arg5] "{edi}" (arg5) | ||||
|           [arg5] "{edi}" (arg5), | ||||
|     ); | ||||
|     const err = asm ("" | ||||
|         : [ret] "={ebx}" (-> usize) | ||||
|         : [ret] "={ebx}" (-> usize), | ||||
|     ); | ||||
|     if (err != 0) { | ||||
|         return syscalls.fromErrorCode(err); | ||||
|  | @ -304,7 +303,7 @@ fn syscall5(syscall: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, | |||
| /// Return: usize | ||||
| ///     The syscall argument from the given index. | ||||
| /// | ||||
| fn syscallArg(ctx: *arch.CpuState, comptime arg_idx: u32) callconv(.Inline) usize { | ||||
| inline fn syscallArg(ctx: *arch.CpuState, comptime arg_idx: u32) usize { | ||||
|     return switch (arg_idx) { | ||||
|         0 => ctx.ebx, | ||||
|         1 => ctx.ecx, | ||||
|  | @ -326,7 +325,7 @@ fn syscallArg(ctx: *arch.CpuState, comptime arg_idx: u32) callconv(.Inline) usiz | |||
| /// | ||||
| fn makeHandler(comptime syscall: syscalls.Syscall) Handler { | ||||
|     return struct { | ||||
|         fn func(ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|         fn func(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|             return syscalls.handle(syscall, arg1, arg2, arg3, arg4, arg5); | ||||
|         } | ||||
|     }.func; | ||||
|  | @ -359,43 +358,69 @@ pub fn init() void { | |||
| /// Tests | ||||
| var test_int: u32 = 0; | ||||
| 
 | ||||
| fn testHandler0(ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
| fn testHandler0(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = arg1; | ||||
|     _ = arg2; | ||||
|     _ = arg3; | ||||
|     _ = arg4; | ||||
|     _ = arg5; | ||||
|     test_int += 1; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| fn testHandler1(ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
| fn testHandler1(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = arg2; | ||||
|     _ = arg3; | ||||
|     _ = arg4; | ||||
|     _ = arg5; | ||||
|     test_int += arg1; | ||||
|     return 1; | ||||
| } | ||||
| 
 | ||||
| fn testHandler2(ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
| fn testHandler2(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = arg3; | ||||
|     _ = arg4; | ||||
|     _ = arg5; | ||||
|     test_int += arg1 + arg2; | ||||
|     return 2; | ||||
| } | ||||
| 
 | ||||
| fn testHandler3(ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
| fn testHandler3(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = arg4; | ||||
|     _ = arg5; | ||||
|     test_int += arg1 + arg2 + arg3; | ||||
|     return 3; | ||||
| } | ||||
| 
 | ||||
| fn testHandler4(ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
| fn testHandler4(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = arg5; | ||||
|     test_int += arg1 + arg2 + arg3 + arg4; | ||||
|     return 4; | ||||
| } | ||||
| 
 | ||||
| fn testHandler5(ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
| fn testHandler5(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|     test_int += arg1 + arg2 + arg3 + arg4 + arg5; | ||||
|     return 5; | ||||
| } | ||||
| 
 | ||||
| fn testHandler6(ctx: *arch.CpuState, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
| fn testHandler6(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) syscalls.Error!usize { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = arg1; | ||||
|     _ = arg2; | ||||
|     _ = arg3; | ||||
|     _ = arg4; | ||||
|     _ = arg5; | ||||
|     return syscalls.Error.OutOfMemory; | ||||
| } | ||||
| 
 | ||||
| test "registerSyscall returns SyscallExists" { | ||||
|     try registerSyscall(122, testHandler0); | ||||
|     std.testing.expectError(Error.SyscallExists, registerSyscall(122, testHandler0)); | ||||
|     try std.testing.expectError(Error.SyscallExists, registerSyscall(122, testHandler0)); | ||||
| } | ||||
| 
 | ||||
| fn runtimeTests() void { | ||||
|  | @ -459,7 +484,7 @@ fn runtimeTests() void { | |||
|         panic(@errorReturnTrace(), "FAILURE syscall5 errored: {}\n", .{e}); | ||||
|     } | ||||
| 
 | ||||
|     if (syscall0(121)) |res| { | ||||
|     if (syscall0(121)) { | ||||
|         panic(@errorReturnTrace(), "FAILURE syscall6\n", .{}); | ||||
|     } else |e| { | ||||
|         if (e != syscalls.Error.OutOfMemory) { | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -4,7 +4,7 @@ const is_test = builtin.is_test; | |||
| const expectEqual = std.testing.expectEqual; | ||||
| const log = std.log.scoped(.x86_vga); | ||||
| const build_options = @import("build_options"); | ||||
| const arch = if (is_test) @import(build_options.arch_mock_path ++ "arch_mock.zig") else @import("arch.zig"); | ||||
| const arch = if (is_test) @import("../../../../test/mock/kernel/arch_mock.zig") else @import("arch.zig"); | ||||
| const panic = @import("../../panic.zig").panic; | ||||
| 
 | ||||
| /// The port address for the VGA register selection. | ||||
|  | @ -121,7 +121,7 @@ var cursor_scanline_end: u8 = undefined; | |||
| ///     IN index: u8 - The index to send to the port address to select the register to write data | ||||
| ///                    to. | ||||
| /// | ||||
| fn sendPort(index: u8) callconv(.Inline) void { | ||||
| inline fn sendPort(index: u8) void { | ||||
|     arch.out(PORT_ADDRESS, index); | ||||
| } | ||||
| 
 | ||||
|  | @ -131,7 +131,7 @@ fn sendPort(index: u8) callconv(.Inline) void { | |||
| /// Arguments: | ||||
| ///     IN data: u8 - The data to send to the selected register. | ||||
| /// | ||||
| fn sendData(data: u8) callconv(.Inline) void { | ||||
| inline fn sendData(data: u8) void { | ||||
|     arch.out(PORT_DATA, data); | ||||
| } | ||||
| 
 | ||||
|  | @ -141,7 +141,7 @@ fn sendData(data: u8) callconv(.Inline) void { | |||
| /// Return: u8 | ||||
| ///     The data in the selected register. | ||||
| /// | ||||
| fn getData() callconv(.Inline) u8 { | ||||
| inline fn getData() u8 { | ||||
|     return arch.in(u8, PORT_DATA); | ||||
| } | ||||
| /// | ||||
|  | @ -152,7 +152,7 @@ fn getData() callconv(.Inline) u8 { | |||
| //                     data to. | ||||
| ///     IN data: u8 - The data to send to the selected register. | ||||
| /// | ||||
| fn sendPortData(index: u8, data: u8) callconv(.Inline) void { | ||||
| inline fn sendPortData(index: u8, data: u8) void { | ||||
|     sendPort(index); | ||||
|     sendData(data); | ||||
| } | ||||
|  | @ -167,7 +167,7 @@ fn sendPortData(index: u8, data: u8) callconv(.Inline) void { | |||
| /// Return: u8 | ||||
| ///     The data in the selected register. | ||||
| /// | ||||
| fn getPortData(index: u8) callconv(.Inline) u8 { | ||||
| inline fn getPortData(index: u8) u8 { | ||||
|     sendPort(index); | ||||
|     return getData(); | ||||
| } | ||||
|  | @ -303,34 +303,34 @@ test "entryColour" { | |||
|     var fg = COLOUR_BLACK; | ||||
|     var bg = COLOUR_BLACK; | ||||
|     var res = entryColour(fg, bg); | ||||
|     expectEqual(@as(u8, 0x00), res); | ||||
|     try expectEqual(@as(u8, 0x00), res); | ||||
| 
 | ||||
|     fg = COLOUR_LIGHT_GREEN; | ||||
|     bg = COLOUR_BLACK; | ||||
|     res = entryColour(fg, bg); | ||||
|     expectEqual(@as(u8, 0x0A), res); | ||||
|     try expectEqual(@as(u8, 0x0A), res); | ||||
| 
 | ||||
|     fg = COLOUR_BLACK; | ||||
|     bg = COLOUR_LIGHT_GREEN; | ||||
|     res = entryColour(fg, bg); | ||||
|     expectEqual(@as(u8, 0xA0), res); | ||||
|     try expectEqual(@as(u8, 0xA0), res); | ||||
| 
 | ||||
|     fg = COLOUR_BROWN; | ||||
|     bg = COLOUR_LIGHT_GREEN; | ||||
|     res = entryColour(fg, bg); | ||||
|     expectEqual(@as(u8, 0xA6), res); | ||||
|     try expectEqual(@as(u8, 0xA6), res); | ||||
| } | ||||
| 
 | ||||
| test "entry" { | ||||
|     const colour = entryColour(COLOUR_BROWN, COLOUR_LIGHT_GREEN); | ||||
|     expectEqual(@as(u8, 0xA6), colour); | ||||
|     try expectEqual(@as(u8, 0xA6), colour); | ||||
| 
 | ||||
|     // Character '0' is 0x30 | ||||
|     var video_entry = entry('0', colour); | ||||
|     expectEqual(@as(u16, 0xA630), video_entry); | ||||
|     try expectEqual(@as(u16, 0xA630), video_entry); | ||||
| 
 | ||||
|     video_entry = entry(0x55, colour); | ||||
|     expectEqual(@as(u16, 0xA655), video_entry); | ||||
|     try expectEqual(@as(u16, 0xA655), video_entry); | ||||
| } | ||||
| 
 | ||||
| test "updateCursor width out of bounds" { | ||||
|  | @ -447,7 +447,7 @@ test "getCursor 1: 10" { | |||
|     arch.addTestParams("in", .{ PORT_DATA, @as(u8, 0) }); | ||||
| 
 | ||||
|     const actual = getCursor(); | ||||
|     expectEqual(expect, actual); | ||||
|     try expectEqual(expect, actual); | ||||
| } | ||||
| 
 | ||||
| test "getCursor 2: 0xBEEF" { | ||||
|  | @ -463,7 +463,7 @@ test "getCursor 2: 0xBEEF" { | |||
|     arch.addTestParams("in", .{ PORT_DATA, @as(u8, 0xBE) }); | ||||
| 
 | ||||
|     const actual = getCursor(); | ||||
|     expectEqual(expect, actual); | ||||
|     try expectEqual(expect, actual); | ||||
| } | ||||
| 
 | ||||
| test "enableCursor" { | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| const std = @import("std"); | ||||
| const builtin = @import("builtin"); | ||||
| const builtin = std.builtin; | ||||
| const testing = std.testing; | ||||
| const Allocator = std.mem.Allocator; | ||||
| 
 | ||||
|  | @ -50,7 +50,7 @@ pub fn ComptimeBitmap(comptime BitmapType: type) type { | |||
|         /// | ||||
|         pub fn setEntry(self: *Self, idx: IndexType) void { | ||||
|             if (!self.isSet(idx)) { | ||||
|                 self.bitmap |= self.indexToBit(idx); | ||||
|                 self.bitmap |= indexToBit(idx); | ||||
|                 self.num_free_entries -= 1; | ||||
|             } | ||||
|         } | ||||
|  | @ -64,7 +64,7 @@ pub fn ComptimeBitmap(comptime BitmapType: type) type { | |||
|         /// | ||||
|         pub fn clearEntry(self: *Self, idx: IndexType) void { | ||||
|             if (self.isSet(idx)) { | ||||
|                 self.bitmap &= ~self.indexToBit(idx); | ||||
|                 self.bitmap &= ~indexToBit(idx); | ||||
|                 self.num_free_entries += 1; | ||||
|             } | ||||
|         } | ||||
|  | @ -79,7 +79,7 @@ pub fn ComptimeBitmap(comptime BitmapType: type) type { | |||
|         /// Return: BitmapType. | ||||
|         ///     The bit corresponding to that index but within a single BitmapType. | ||||
|         /// | ||||
|         fn indexToBit(self: *const Self, idx: IndexType) BitmapType { | ||||
|         fn indexToBit(idx: IndexType) BitmapType { | ||||
|             return @as(BitmapType, 1) << idx; | ||||
|         } | ||||
| 
 | ||||
|  | @ -178,7 +178,7 @@ pub fn ComptimeBitmap(comptime BitmapType: type) type { | |||
|         ///     True if the entry is set, else false. | ||||
|         /// | ||||
|         pub fn isSet(self: *const Self, idx: IndexType) bool { | ||||
|             return (self.bitmap & self.indexToBit(idx)) != 0; | ||||
|             return (self.bitmap & indexToBit(idx)) != 0; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | @ -215,7 +215,7 @@ pub fn Bitmap(comptime BitmapType: type) type { | |||
|         num_entries: usize, | ||||
|         bitmaps: []BitmapType, | ||||
|         num_free_entries: usize, | ||||
|         allocator: *std.mem.Allocator, | ||||
|         allocator: Allocator, | ||||
| 
 | ||||
|         /// | ||||
|         /// Create an instance of this bitmap type. | ||||
|  | @ -223,15 +223,15 @@ pub fn Bitmap(comptime BitmapType: type) type { | |||
|         /// Arguments: | ||||
|         ///     IN num_entries: usize - The number of entries that the bitmap created will have. | ||||
|         ///         The number of BitmapType required to store this many entries will be allocated and each will be zeroed. | ||||
|         ///     IN allocator: *std.mem.Allocator - The allocator to use when allocating the BitmapTypes required. | ||||
|         ///     IN allocator: Allocator - The allocator to use when allocating the BitmapTypes required. | ||||
|         /// | ||||
|         /// Return: Self. | ||||
|         ///     The bitmap instance. | ||||
|         /// | ||||
|         /// Error: std.mem.Allocator.Error | ||||
|         /// Error: Allocator.Error | ||||
|         ///     OutOfMemory: There isn't enough memory available to allocate the required number of BitmapType. | ||||
|         /// | ||||
|         pub fn init(num_entries: usize, allocator: *std.mem.Allocator) !Self { | ||||
|         pub fn init(num_entries: usize, allocator: Allocator) !Self { | ||||
|             const num = std.mem.alignForward(num_entries, ENTRIES_PER_BITMAP) / ENTRIES_PER_BITMAP; | ||||
|             const self = Self{ | ||||
|                 .num_bitmaps = num, | ||||
|  | @ -255,10 +255,10 @@ pub fn Bitmap(comptime BitmapType: type) type { | |||
|         /// Return: Self | ||||
|         ///     The cloned bitmap | ||||
|         /// | ||||
|         /// Error: std.mem.Allocator.Error | ||||
|         /// Error: Allocator.Error | ||||
|         ///     OutOfMemory: There isn't enough memory available to allocate the required number of BitmapType. | ||||
|         /// | ||||
|         pub fn clone(self: *const Self) std.mem.Allocator.Error!Self { | ||||
|         pub fn clone(self: *const Self) Allocator.Error!Self { | ||||
|             var copy = try init(self.num_entries, self.allocator); | ||||
|             var i: usize = 0; | ||||
|             while (i < copy.num_entries) : (i += 1) { | ||||
|  | @ -294,7 +294,7 @@ pub fn Bitmap(comptime BitmapType: type) type { | |||
|                 return BitmapError.OutOfBounds; | ||||
|             } | ||||
|             if (!try self.isSet(idx)) { | ||||
|                 const bit = self.indexToBit(idx); | ||||
|                 const bit = indexToBit(idx); | ||||
|                 self.bitmaps[idx / ENTRIES_PER_BITMAP] |= bit; | ||||
|                 self.num_free_entries -= 1; | ||||
|             } | ||||
|  | @ -315,7 +315,7 @@ pub fn Bitmap(comptime BitmapType: type) type { | |||
|                 return BitmapError.OutOfBounds; | ||||
|             } | ||||
|             if (try self.isSet(idx)) { | ||||
|                 const bit = self.indexToBit(idx); | ||||
|                 const bit = indexToBit(idx); | ||||
|                 self.bitmaps[idx / ENTRIES_PER_BITMAP] &= ~bit; | ||||
|                 self.num_free_entries += 1; | ||||
|             } | ||||
|  | @ -331,7 +331,7 @@ pub fn Bitmap(comptime BitmapType: type) type { | |||
|         /// Return: BitmapType. | ||||
|         ///     The bit corresponding to that index but within a single BitmapType. | ||||
|         /// | ||||
|         fn indexToBit(self: *const Self, idx: usize) BitmapType { | ||||
|         fn indexToBit(idx: usize) BitmapType { | ||||
|             return @as(BitmapType, 1) << @intCast(IndexType, idx % ENTRIES_PER_BITMAP); | ||||
|         } | ||||
| 
 | ||||
|  | @ -454,73 +454,73 @@ pub fn Bitmap(comptime BitmapType: type) type { | |||
|             if (idx >= self.num_entries) { | ||||
|                 return BitmapError.OutOfBounds; | ||||
|             } | ||||
|             return (self.bitmaps[idx / ENTRIES_PER_BITMAP] & self.indexToBit(idx)) != 0; | ||||
|             return (self.bitmaps[idx / ENTRIES_PER_BITMAP] & indexToBit(idx)) != 0; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| test "Comptime setEntry" { | ||||
|     var bmp = ComptimeBitmap(u32).init(); | ||||
|     testing.expectEqual(@as(u32, 32), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 32), bmp.num_free_entries); | ||||
| 
 | ||||
|     bmp.setEntry(0); | ||||
|     testing.expectEqual(@as(u32, 1), bmp.bitmap); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 1), bmp.bitmap); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
| 
 | ||||
|     bmp.setEntry(1); | ||||
|     testing.expectEqual(@as(u32, 3), bmp.bitmap); | ||||
|     testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 3), bmp.bitmap); | ||||
|     try testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
| 
 | ||||
|     // Repeat setting entry 1 to make sure state doesn't change | ||||
|     bmp.setEntry(1); | ||||
|     testing.expectEqual(@as(u32, 3), bmp.bitmap); | ||||
|     testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 3), bmp.bitmap); | ||||
|     try testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
| } | ||||
| 
 | ||||
| test "Comptime clearEntry" { | ||||
|     var bmp = ComptimeBitmap(u32).init(); | ||||
|     testing.expectEqual(@as(u32, 32), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 32), bmp.num_free_entries); | ||||
| 
 | ||||
|     bmp.setEntry(0); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     bmp.setEntry(1); | ||||
|     testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
|     testing.expectEqual(@as(u32, 3), bmp.bitmap); | ||||
|     try testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 3), bmp.bitmap); | ||||
|     bmp.clearEntry(0); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     testing.expectEqual(@as(u32, 2), bmp.bitmap); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 2), bmp.bitmap); | ||||
| 
 | ||||
|     // Repeat to make sure state doesn't change | ||||
|     bmp.clearEntry(0); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     testing.expectEqual(@as(u32, 2), bmp.bitmap); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 2), bmp.bitmap); | ||||
| 
 | ||||
|     // Try clearing an unset entry to make sure state doesn't change | ||||
|     bmp.clearEntry(2); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     testing.expectEqual(@as(u32, 2), bmp.bitmap); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 2), bmp.bitmap); | ||||
| } | ||||
| 
 | ||||
| test "Comptime setFirstFree" { | ||||
|     var bmp = ComptimeBitmap(u32).init(); | ||||
| 
 | ||||
|     // Allocate the first entry | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, 0); | ||||
|     testing.expectEqual(bmp.bitmap, 1); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, 0); | ||||
|     try testing.expectEqual(bmp.bitmap, 1); | ||||
| 
 | ||||
|     // Allocate the second entry | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, 1); | ||||
|     testing.expectEqual(bmp.bitmap, 3); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, 1); | ||||
|     try testing.expectEqual(bmp.bitmap, 3); | ||||
| 
 | ||||
|     // Make all but the MSB occupied and try to allocate it | ||||
|     bmp.bitmap = ComptimeBitmap(u32).BITMAP_FULL & ~@as(u32, 1 << (ComptimeBitmap(u32).NUM_ENTRIES - 1)); | ||||
|     bmp.num_free_entries = 1; | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, ComptimeBitmap(u32).NUM_ENTRIES - 1); | ||||
|     testing.expectEqual(bmp.bitmap, ComptimeBitmap(u32).BITMAP_FULL); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, ComptimeBitmap(u32).NUM_ENTRIES - 1); | ||||
|     try testing.expectEqual(bmp.bitmap, ComptimeBitmap(u32).BITMAP_FULL); | ||||
| 
 | ||||
|     // We should no longer be able to allocate any entries | ||||
|     testing.expectEqual(bmp.setFirstFree(), null); | ||||
|     testing.expectEqual(bmp.bitmap, ComptimeBitmap(u32).BITMAP_FULL); | ||||
|     try testing.expectEqual(bmp.setFirstFree(), null); | ||||
|     try testing.expectEqual(bmp.bitmap, ComptimeBitmap(u32).BITMAP_FULL); | ||||
| } | ||||
| 
 | ||||
| test "Comptime isSet" { | ||||
|  | @ -528,127 +528,127 @@ test "Comptime isSet" { | |||
| 
 | ||||
|     bmp.bitmap = 1; | ||||
|     // Make sure that only the set entry is considered set | ||||
|     testing.expect(bmp.isSet(0)); | ||||
|     try testing.expect(bmp.isSet(0)); | ||||
|     var i: usize = 1; | ||||
|     while (i < ComptimeBitmap(u32).NUM_ENTRIES) : (i += 1) { | ||||
|         testing.expect(!bmp.isSet(@truncate(ComptimeBitmap(u32).IndexType, i))); | ||||
|         try testing.expect(!bmp.isSet(@truncate(ComptimeBitmap(u32).IndexType, i))); | ||||
|     } | ||||
| 
 | ||||
|     bmp.bitmap = 3; | ||||
|     testing.expect(bmp.isSet(0)); | ||||
|     testing.expect(bmp.isSet(1)); | ||||
|     try testing.expect(bmp.isSet(0)); | ||||
|     try testing.expect(bmp.isSet(1)); | ||||
|     i = 2; | ||||
|     while (i < ComptimeBitmap(u32).NUM_ENTRIES) : (i += 1) { | ||||
|         testing.expect(!bmp.isSet(@truncate(ComptimeBitmap(u32).IndexType, i))); | ||||
|         try testing.expect(!bmp.isSet(@truncate(ComptimeBitmap(u32).IndexType, i))); | ||||
|     } | ||||
| 
 | ||||
|     bmp.bitmap = 11; | ||||
|     testing.expect(bmp.isSet(0)); | ||||
|     testing.expect(bmp.isSet(1)); | ||||
|     testing.expect(!bmp.isSet(2)); | ||||
|     testing.expect(bmp.isSet(3)); | ||||
|     try testing.expect(bmp.isSet(0)); | ||||
|     try testing.expect(bmp.isSet(1)); | ||||
|     try testing.expect(!bmp.isSet(2)); | ||||
|     try testing.expect(bmp.isSet(3)); | ||||
|     i = 4; | ||||
|     while (i < ComptimeBitmap(u32).NUM_ENTRIES) : (i += 1) { | ||||
|         testing.expect(!bmp.isSet(@truncate(ComptimeBitmap(u32).IndexType, i))); | ||||
|         try testing.expect(!bmp.isSet(@truncate(ComptimeBitmap(u32).IndexType, i))); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| test "Comptime indexToBit" { | ||||
|     var bmp = ComptimeBitmap(u8).init(); | ||||
|     testing.expectEqual(bmp.indexToBit(0), 1); | ||||
|     testing.expectEqual(bmp.indexToBit(1), 2); | ||||
|     testing.expectEqual(bmp.indexToBit(2), 4); | ||||
|     testing.expectEqual(bmp.indexToBit(3), 8); | ||||
|     testing.expectEqual(bmp.indexToBit(4), 16); | ||||
|     testing.expectEqual(bmp.indexToBit(5), 32); | ||||
|     testing.expectEqual(bmp.indexToBit(6), 64); | ||||
|     testing.expectEqual(bmp.indexToBit(7), 128); | ||||
|     const Type = ComptimeBitmap(u8); | ||||
|     try testing.expectEqual(Type.indexToBit(0), 1); | ||||
|     try testing.expectEqual(Type.indexToBit(1), 2); | ||||
|     try testing.expectEqual(Type.indexToBit(2), 4); | ||||
|     try testing.expectEqual(Type.indexToBit(3), 8); | ||||
|     try testing.expectEqual(Type.indexToBit(4), 16); | ||||
|     try testing.expectEqual(Type.indexToBit(5), 32); | ||||
|     try testing.expectEqual(Type.indexToBit(6), 64); | ||||
|     try testing.expectEqual(Type.indexToBit(7), 128); | ||||
| } | ||||
| 
 | ||||
| test "Comptime setContiguous" { | ||||
|     var bmp = ComptimeBitmap(u16).init(); | ||||
|     // Test trying to set more entries than the bitmap has | ||||
|     testing.expectEqual(bmp.setContiguous(bmp.num_free_entries + 1, null), null); | ||||
|     testing.expectEqual(bmp.setContiguous(bmp.num_free_entries + 1, 1), null); | ||||
|     try testing.expectEqual(bmp.setContiguous(bmp.num_free_entries + 1, null), null); | ||||
|     try testing.expectEqual(bmp.setContiguous(bmp.num_free_entries + 1, 1), null); | ||||
|     // All entries should still be free | ||||
|     testing.expectEqual(bmp.num_free_entries, 16); | ||||
|     testing.expectEqual(bmp.bitmap, 0b0000000000000000); | ||||
|     try testing.expectEqual(bmp.num_free_entries, 16); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b0000000000000000); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(3, 0) orelse unreachable, 0); | ||||
|     testing.expectEqual(bmp.bitmap, 0b0000000000000111); | ||||
|     try testing.expectEqual(bmp.setContiguous(3, 0) orelse unreachable, 0); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b0000000000000111); | ||||
| 
 | ||||
|     // Test setting from top | ||||
|     testing.expectEqual(bmp.setContiguous(2, 14) orelse unreachable, 14); | ||||
|     testing.expectEqual(bmp.bitmap, 0b1100000000000111); | ||||
|     try testing.expectEqual(bmp.setContiguous(2, 14) orelse unreachable, 14); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b1100000000000111); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(3, 12), null); | ||||
|     testing.expectEqual(bmp.bitmap, 0b1100000000000111); | ||||
|     try testing.expectEqual(bmp.setContiguous(3, 12), null); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b1100000000000111); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(3, null) orelse unreachable, 3); | ||||
|     testing.expectEqual(bmp.bitmap, 0b1100000000111111); | ||||
|     try testing.expectEqual(bmp.setContiguous(3, null) orelse unreachable, 3); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b1100000000111111); | ||||
| 
 | ||||
|     // Test setting beyond the what is available | ||||
|     testing.expectEqual(bmp.setContiguous(9, null), null); | ||||
|     testing.expectEqual(bmp.bitmap, 0b1100000000111111); | ||||
|     try testing.expectEqual(bmp.setContiguous(9, null), null); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b1100000000111111); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(8, null) orelse unreachable, 6); | ||||
|     testing.expectEqual(bmp.bitmap, 0b1111111111111111); | ||||
|     try testing.expectEqual(bmp.setContiguous(8, null) orelse unreachable, 6); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b1111111111111111); | ||||
| 
 | ||||
|     // No more are possible | ||||
|     testing.expectEqual(bmp.setContiguous(1, null), null); | ||||
|     testing.expectEqual(bmp.bitmap, 0b1111111111111111); | ||||
|     try testing.expectEqual(bmp.setContiguous(1, null), null); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b1111111111111111); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(1, 0), null); | ||||
|     testing.expectEqual(bmp.bitmap, 0b1111111111111111); | ||||
|     try testing.expectEqual(bmp.setContiguous(1, 0), null); | ||||
|     try testing.expectEqual(bmp.bitmap, 0b1111111111111111); | ||||
| } | ||||
| 
 | ||||
| test "setEntry" { | ||||
|     var bmp = try Bitmap(u32).init(31, std.testing.allocator); | ||||
|     defer bmp.deinit(); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
| 
 | ||||
|     try bmp.setEntry(0); | ||||
|     testing.expectEqual(@as(u32, 1), bmp.bitmaps[0]); | ||||
|     testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 1), bmp.bitmaps[0]); | ||||
|     try testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
| 
 | ||||
|     try bmp.setEntry(1); | ||||
|     testing.expectEqual(@as(u32, 3), bmp.bitmaps[0]); | ||||
|     testing.expectEqual(@as(u32, 29), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 3), bmp.bitmaps[0]); | ||||
|     try testing.expectEqual(@as(u32, 29), bmp.num_free_entries); | ||||
| 
 | ||||
|     // Repeat setting entry 1 to make sure state doesn't change | ||||
|     try bmp.setEntry(1); | ||||
|     testing.expectEqual(@as(u32, 3), bmp.bitmaps[0]); | ||||
|     testing.expectEqual(@as(u32, 29), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 3), bmp.bitmaps[0]); | ||||
|     try testing.expectEqual(@as(u32, 29), bmp.num_free_entries); | ||||
| 
 | ||||
|     testing.expectError(Bitmap(u32).BitmapError.OutOfBounds, bmp.setEntry(31)); | ||||
|     testing.expectEqual(@as(u32, 29), bmp.num_free_entries); | ||||
|     try testing.expectError(Bitmap(u32).BitmapError.OutOfBounds, bmp.setEntry(31)); | ||||
|     try testing.expectEqual(@as(u32, 29), bmp.num_free_entries); | ||||
| } | ||||
| 
 | ||||
| test "clearEntry" { | ||||
|     var bmp = try Bitmap(u32).init(32, std.testing.allocator); | ||||
|     defer bmp.deinit(); | ||||
|     testing.expectEqual(@as(u32, 32), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 32), bmp.num_free_entries); | ||||
| 
 | ||||
|     try bmp.setEntry(0); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try bmp.setEntry(1); | ||||
|     testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
|     testing.expectEqual(@as(u32, 3), bmp.bitmaps[0]); | ||||
|     try testing.expectEqual(@as(u32, 30), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 3), bmp.bitmaps[0]); | ||||
|     try bmp.clearEntry(0); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     testing.expectEqual(@as(u32, 2), bmp.bitmaps[0]); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 2), bmp.bitmaps[0]); | ||||
| 
 | ||||
|     // Repeat to make sure state doesn't change | ||||
|     try bmp.clearEntry(0); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     testing.expectEqual(@as(u32, 2), bmp.bitmaps[0]); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 2), bmp.bitmaps[0]); | ||||
| 
 | ||||
|     // Try clearing an unset entry to make sure state doesn't change | ||||
|     try bmp.clearEntry(2); | ||||
|     testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     testing.expectEqual(@as(u32, 2), bmp.bitmaps[0]); | ||||
|     try testing.expectEqual(@as(u32, 31), bmp.num_free_entries); | ||||
|     try testing.expectEqual(@as(u32, 2), bmp.bitmaps[0]); | ||||
| 
 | ||||
|     testing.expectError(Bitmap(u32).BitmapError.OutOfBounds, bmp.clearEntry(32)); | ||||
|     try testing.expectError(Bitmap(u32).BitmapError.OutOfBounds, bmp.clearEntry(32)); | ||||
| } | ||||
| 
 | ||||
| test "setFirstFree multiple bitmaps" { | ||||
|  | @ -656,19 +656,19 @@ test "setFirstFree multiple bitmaps" { | |||
|     defer bmp.deinit(); | ||||
| 
 | ||||
|     // Allocate the first entry | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, 0); | ||||
|     testing.expectEqual(bmp.bitmaps[0], 1); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, 0); | ||||
|     try testing.expectEqual(bmp.bitmaps[0], 1); | ||||
| 
 | ||||
|     // Allocate the second entry | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, 1); | ||||
|     testing.expectEqual(bmp.bitmaps[0], 3); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, 1); | ||||
|     try testing.expectEqual(bmp.bitmaps[0], 3); | ||||
| 
 | ||||
|     // Allocate the entirety of the first bitmap | ||||
|     var entry: u32 = 2; | ||||
|     var expected: u8 = 7; | ||||
|     while (entry < Bitmap(u8).ENTRIES_PER_BITMAP) { | ||||
|         testing.expectEqual(bmp.setFirstFree() orelse unreachable, entry); | ||||
|         testing.expectEqual(bmp.bitmaps[0], expected); | ||||
|         try testing.expectEqual(bmp.setFirstFree() orelse unreachable, entry); | ||||
|         try testing.expectEqual(bmp.bitmaps[0], expected); | ||||
|         if (entry + 1 < Bitmap(u8).ENTRIES_PER_BITMAP) { | ||||
|             entry += 1; | ||||
|             expected = expected * 2 + 1; | ||||
|  | @ -678,14 +678,14 @@ test "setFirstFree multiple bitmaps" { | |||
|     } | ||||
| 
 | ||||
|     // Try allocating an entry in the next bitmap | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, Bitmap(u8).ENTRIES_PER_BITMAP); | ||||
|     testing.expectEqual(bmp.bitmaps[0], Bitmap(u8).BITMAP_FULL); | ||||
|     testing.expectEqual(bmp.bitmaps[1], 1); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, Bitmap(u8).ENTRIES_PER_BITMAP); | ||||
|     try testing.expectEqual(bmp.bitmaps[0], Bitmap(u8).BITMAP_FULL); | ||||
|     try testing.expectEqual(bmp.bitmaps[1], 1); | ||||
| 
 | ||||
|     // We should no longer be able to allocate any entries | ||||
|     testing.expectEqual(bmp.setFirstFree(), null); | ||||
|     testing.expectEqual(bmp.bitmaps[0], Bitmap(u8).BITMAP_FULL); | ||||
|     testing.expectEqual(bmp.bitmaps[1], 1); | ||||
|     try testing.expectEqual(bmp.setFirstFree(), null); | ||||
|     try testing.expectEqual(bmp.bitmaps[0], Bitmap(u8).BITMAP_FULL); | ||||
|     try testing.expectEqual(bmp.bitmaps[1], 1); | ||||
| } | ||||
| 
 | ||||
| test "setFirstFree" { | ||||
|  | @ -693,21 +693,21 @@ test "setFirstFree" { | |||
|     defer bmp.deinit(); | ||||
| 
 | ||||
|     // Allocate the first entry | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, 0); | ||||
|     testing.expectEqual(bmp.bitmaps[0], 1); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, 0); | ||||
|     try testing.expectEqual(bmp.bitmaps[0], 1); | ||||
| 
 | ||||
|     // Allocate the second entry | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, 1); | ||||
|     testing.expectEqual(bmp.bitmaps[0], 3); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, 1); | ||||
|     try testing.expectEqual(bmp.bitmaps[0], 3); | ||||
| 
 | ||||
|     // Make all but the MSB occupied and try to allocate it | ||||
|     bmp.bitmaps[0] = Bitmap(u32).BITMAP_FULL & ~@as(u32, 1 << (Bitmap(u32).ENTRIES_PER_BITMAP - 1)); | ||||
|     testing.expectEqual(bmp.setFirstFree() orelse unreachable, Bitmap(u32).ENTRIES_PER_BITMAP - 1); | ||||
|     testing.expectEqual(bmp.bitmaps[0], Bitmap(u32).BITMAP_FULL); | ||||
|     try testing.expectEqual(bmp.setFirstFree() orelse unreachable, Bitmap(u32).ENTRIES_PER_BITMAP - 1); | ||||
|     try testing.expectEqual(bmp.bitmaps[0], Bitmap(u32).BITMAP_FULL); | ||||
| 
 | ||||
|     // We should no longer be able to allocate any entries | ||||
|     testing.expectEqual(bmp.setFirstFree(), null); | ||||
|     testing.expectEqual(bmp.bitmaps[0], Bitmap(u32).BITMAP_FULL); | ||||
|     try testing.expectEqual(bmp.setFirstFree(), null); | ||||
|     try testing.expectEqual(bmp.bitmaps[0], Bitmap(u32).BITMAP_FULL); | ||||
| } | ||||
| 
 | ||||
| test "isSet" { | ||||
|  | @ -716,89 +716,90 @@ test "isSet" { | |||
| 
 | ||||
|     bmp.bitmaps[0] = 1; | ||||
|     // Make sure that only the set entry is considered set | ||||
|     testing.expect(try bmp.isSet(0)); | ||||
|     try testing.expect(try bmp.isSet(0)); | ||||
|     var i: u32 = 1; | ||||
|     while (i < bmp.num_entries) : (i += 1) { | ||||
|         testing.expect(!try bmp.isSet(i)); | ||||
|         try testing.expect(!try bmp.isSet(i)); | ||||
|     } | ||||
| 
 | ||||
|     bmp.bitmaps[0] = 3; | ||||
|     testing.expect(try bmp.isSet(0)); | ||||
|     testing.expect(try bmp.isSet(1)); | ||||
|     try testing.expect(try bmp.isSet(0)); | ||||
|     try testing.expect(try bmp.isSet(1)); | ||||
|     i = 2; | ||||
|     while (i < bmp.num_entries) : (i += 1) { | ||||
|         testing.expect(!try bmp.isSet(i)); | ||||
|         try testing.expect(!try bmp.isSet(i)); | ||||
|     } | ||||
| 
 | ||||
|     bmp.bitmaps[0] = 11; | ||||
|     testing.expect(try bmp.isSet(0)); | ||||
|     testing.expect(try bmp.isSet(1)); | ||||
|     testing.expect(!try bmp.isSet(2)); | ||||
|     testing.expect(try bmp.isSet(3)); | ||||
|     try testing.expect(try bmp.isSet(0)); | ||||
|     try testing.expect(try bmp.isSet(1)); | ||||
|     try testing.expect(!try bmp.isSet(2)); | ||||
|     try testing.expect(try bmp.isSet(3)); | ||||
|     i = 4; | ||||
|     while (i < bmp.num_entries) : (i += 1) { | ||||
|         testing.expect(!try bmp.isSet(i)); | ||||
|         try testing.expect(!try bmp.isSet(i)); | ||||
|     } | ||||
| 
 | ||||
|     testing.expectError(Bitmap(u32).BitmapError.OutOfBounds, bmp.isSet(33)); | ||||
|     try testing.expectError(Bitmap(u32).BitmapError.OutOfBounds, bmp.isSet(33)); | ||||
| } | ||||
| 
 | ||||
| test "indexToBit" { | ||||
|     var bmp = try Bitmap(u8).init(10, std.testing.allocator); | ||||
|     const Type = Bitmap(u8); | ||||
|     var bmp = try Type.init(10, std.testing.allocator); | ||||
|     defer bmp.deinit(); | ||||
|     testing.expectEqual(bmp.indexToBit(0), 1); | ||||
|     testing.expectEqual(bmp.indexToBit(1), 2); | ||||
|     testing.expectEqual(bmp.indexToBit(2), 4); | ||||
|     testing.expectEqual(bmp.indexToBit(3), 8); | ||||
|     testing.expectEqual(bmp.indexToBit(4), 16); | ||||
|     testing.expectEqual(bmp.indexToBit(5), 32); | ||||
|     testing.expectEqual(bmp.indexToBit(6), 64); | ||||
|     testing.expectEqual(bmp.indexToBit(7), 128); | ||||
|     testing.expectEqual(bmp.indexToBit(8), 1); | ||||
|     testing.expectEqual(bmp.indexToBit(9), 2); | ||||
|     try testing.expectEqual(Type.indexToBit(0), 1); | ||||
|     try testing.expectEqual(Type.indexToBit(1), 2); | ||||
|     try testing.expectEqual(Type.indexToBit(2), 4); | ||||
|     try testing.expectEqual(Type.indexToBit(3), 8); | ||||
|     try testing.expectEqual(Type.indexToBit(4), 16); | ||||
|     try testing.expectEqual(Type.indexToBit(5), 32); | ||||
|     try testing.expectEqual(Type.indexToBit(6), 64); | ||||
|     try testing.expectEqual(Type.indexToBit(7), 128); | ||||
|     try testing.expectEqual(Type.indexToBit(8), 1); | ||||
|     try testing.expectEqual(Type.indexToBit(9), 2); | ||||
| } | ||||
| 
 | ||||
| fn testCheckBitmaps(bmp: Bitmap(u4), b1: u4, b2: u4, b3: u4, b4: u4) void { | ||||
|     testing.expectEqual(@as(u4, b1), bmp.bitmaps[0]); | ||||
|     testing.expectEqual(@as(u4, b2), bmp.bitmaps[1]); | ||||
|     testing.expectEqual(@as(u4, b3), bmp.bitmaps[2]); | ||||
|     testing.expectEqual(@as(u4, b4), bmp.bitmaps[3]); | ||||
| fn testCheckBitmaps(bmp: Bitmap(u4), b1: u4, b2: u4, b3: u4, b4: u4) !void { | ||||
|     try testing.expectEqual(@as(u4, b1), bmp.bitmaps[0]); | ||||
|     try testing.expectEqual(@as(u4, b2), bmp.bitmaps[1]); | ||||
|     try testing.expectEqual(@as(u4, b3), bmp.bitmaps[2]); | ||||
|     try testing.expectEqual(@as(u4, b4), bmp.bitmaps[3]); | ||||
| } | ||||
| 
 | ||||
| test "setContiguous" { | ||||
|     var bmp = try Bitmap(u4).init(16, std.testing.allocator); | ||||
|     defer bmp.deinit(); | ||||
|     // Test trying to set more entries than the bitmap has | ||||
|     testing.expectEqual(bmp.setContiguous(bmp.num_entries + 1, null), null); | ||||
|     testing.expectEqual(bmp.setContiguous(bmp.num_entries + 1, 1), null); | ||||
|     try testing.expectEqual(bmp.setContiguous(bmp.num_entries + 1, null), null); | ||||
|     try testing.expectEqual(bmp.setContiguous(bmp.num_entries + 1, 1), null); | ||||
|     // All entries should still be free | ||||
|     testing.expectEqual(bmp.num_free_entries, bmp.num_entries); | ||||
|     testCheckBitmaps(bmp, 0, 0, 0, 0); | ||||
|     try testing.expectEqual(bmp.num_free_entries, bmp.num_entries); | ||||
|     try testCheckBitmaps(bmp, 0, 0, 0, 0); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(3, 0) orelse unreachable, 0); | ||||
|     testCheckBitmaps(bmp, 0b0111, 0, 0, 0); | ||||
|     try testing.expectEqual(bmp.setContiguous(3, 0) orelse unreachable, 0); | ||||
|     try testCheckBitmaps(bmp, 0b0111, 0, 0, 0); | ||||
| 
 | ||||
|     // Test setting from top | ||||
|     testing.expectEqual(bmp.setContiguous(2, 14) orelse unreachable, 14); | ||||
|     testCheckBitmaps(bmp, 0b0111, 0, 0, 0b1100); | ||||
|     try testing.expectEqual(bmp.setContiguous(2, 14) orelse unreachable, 14); | ||||
|     try testCheckBitmaps(bmp, 0b0111, 0, 0, 0b1100); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(3, 12), null); | ||||
|     testCheckBitmaps(bmp, 0b0111, 0, 0, 0b1100); | ||||
|     try testing.expectEqual(bmp.setContiguous(3, 12), null); | ||||
|     try testCheckBitmaps(bmp, 0b0111, 0, 0, 0b1100); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(3, null) orelse unreachable, 3); | ||||
|     testCheckBitmaps(bmp, 0b1111, 0b0011, 0, 0b1100); | ||||
|     try testing.expectEqual(bmp.setContiguous(3, null) orelse unreachable, 3); | ||||
|     try testCheckBitmaps(bmp, 0b1111, 0b0011, 0, 0b1100); | ||||
| 
 | ||||
|     // Test setting beyond the what is available | ||||
|     testing.expectEqual(bmp.setContiguous(9, null), null); | ||||
|     testCheckBitmaps(bmp, 0b1111, 0b0011, 0, 0b1100); | ||||
|     try testing.expectEqual(bmp.setContiguous(9, null), null); | ||||
|     try testCheckBitmaps(bmp, 0b1111, 0b0011, 0, 0b1100); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(8, null) orelse unreachable, 6); | ||||
|     testCheckBitmaps(bmp, 0b1111, 0b1111, 0b1111, 0b1111); | ||||
|     try testing.expectEqual(bmp.setContiguous(8, null) orelse unreachable, 6); | ||||
|     try testCheckBitmaps(bmp, 0b1111, 0b1111, 0b1111, 0b1111); | ||||
| 
 | ||||
|     // No more are possible | ||||
|     testing.expectEqual(bmp.setContiguous(1, null), null); | ||||
|     testCheckBitmaps(bmp, 0b1111, 0b1111, 0b1111, 0b1111); | ||||
|     try testing.expectEqual(bmp.setContiguous(1, null), null); | ||||
|     try testCheckBitmaps(bmp, 0b1111, 0b1111, 0b1111, 0b1111); | ||||
| 
 | ||||
|     testing.expectEqual(bmp.setContiguous(1, 0), null); | ||||
|     testCheckBitmaps(bmp, 0b1111, 0b1111, 0b1111, 0b1111); | ||||
|     try testing.expectEqual(bmp.setContiguous(1, 0), null); | ||||
|     try testCheckBitmaps(bmp, 0b1111, 0b1111, 0b1111, 0b1111); | ||||
| } | ||||
|  |  | |||
|  | @ -78,7 +78,7 @@ test "ASCII toCodePage" { | |||
|     var ascii: u8 = 0x20; | ||||
|     while (ascii < 0x7F) : (ascii += 1) { | ||||
|         const char = try CodePage.toCodePage(.CP437, ascii); | ||||
|         std.testing.expectEqual(char, ascii); | ||||
|         try std.testing.expectEqual(char, ascii); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -87,11 +87,11 @@ test "ASCII toWideChar" { | |||
|     var ascii: u8 = 0x20; | ||||
|     while (ascii < 0x7F) : (ascii += 1) { | ||||
|         const char = CodePage.toWideChar(.CP437, ascii); | ||||
|         std.testing.expectEqual(char, ascii); | ||||
|         try std.testing.expectEqual(char, ascii); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| test "Invalid characters" { | ||||
|     const char = '€'; | ||||
|     std.testing.expectError(CodePage.Error.InvalidChar, CodePage.toCodePage(.CP437, char)); | ||||
|     try std.testing.expectError(CodePage.Error.InvalidChar, CodePage.toCodePage(.CP437, char)); | ||||
| } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| const std = @import("std"); | ||||
| const builtin = @import("builtin"); | ||||
| const Arch = std.Target.Cpu.Arch; | ||||
| const Endian = builtin.Endian; | ||||
| const Endian = std.builtin.Endian; | ||||
| const log = std.log.scoped(.elf); | ||||
| const testing = std.testing; | ||||
| 
 | ||||
|  | @ -366,7 +366,7 @@ pub const Elf = struct { | |||
|     /// The data associated with each section, or null if a section doesn't have a data area | ||||
|     section_data: []?[]const u8, | ||||
|     /// The allocator used | ||||
|     allocator: *std.mem.Allocator, | ||||
|     allocator: std.mem.Allocator, | ||||
| 
 | ||||
|     const Self = @This(); | ||||
| 
 | ||||
|  | @ -389,7 +389,7 @@ pub const Elf = struct { | |||
|     ///     Error.InvalidEndianness - The ELF file wasn't built with the endianness supported by the given architecture | ||||
|     ///     Error.WrongStringTableIndex - The string table index in the header does not point to a StringTable section | ||||
|     /// | ||||
|     pub fn init(elf_data: []const u8, arch: Arch, allocator: *std.mem.Allocator) (std.mem.Allocator.Error || Error)!Self { | ||||
|     pub fn init(elf_data: []const u8, arch: Arch, allocator: std.mem.Allocator) (std.mem.Allocator.Error || Error)!Self { | ||||
|         const header = std.mem.bytesToValue(Header, elf_data[0..@sizeOf(Header)]); | ||||
|         if (header.magic_number != 0x464C457F) { | ||||
|             return Error.InvalidMagicNumber; | ||||
|  | @ -464,7 +464,7 @@ fn testSetSection(data: []u8, header: SectionHeader, idx: usize) void { | |||
|     std.mem.copy(u8, dest, @ptrCast([*]const u8, &header)[0..@sizeOf(SectionHeader)]); | ||||
| } | ||||
| 
 | ||||
| pub fn testInitData(allocator: *std.mem.Allocator, section_name: []const u8, string_section_name: []const u8, file_type: Type, entry_address: usize, flags: u32, section_flags: u32, strings_flags: u32, section_address: usize, strings_address: usize) ![]u8 { | ||||
| pub fn testInitData(allocator: std.mem.Allocator, section_name: []const u8, string_section_name: []const u8, file_type: Type, entry_address: usize, flags: u32, section_flags: u32, strings_flags: u32, section_address: usize, strings_address: usize) ![]u8 { | ||||
|     const is_32_bit = @bitSizeOf(usize) == 32; | ||||
|     const header_size = if (is_32_bit) 0x34 else 0x40; | ||||
|     const p_header_size = if (is_32_bit) 0x20 else 0x38; | ||||
|  | @ -480,7 +480,7 @@ pub fn testInitData(allocator: *std.mem.Allocator, section_name: []const u8, str | |||
|             64 => .SixtyFourBit, | ||||
|             else => unreachable, | ||||
|         }, | ||||
|         .endianness = switch (builtin.arch.endian()) { | ||||
|         .endianness = switch (builtin.cpu.arch.endian()) { | ||||
|             .Big => .Big, | ||||
|             .Little => .Little, | ||||
|         }, | ||||
|  | @ -491,7 +491,7 @@ pub fn testInitData(allocator: *std.mem.Allocator, section_name: []const u8, str | |||
|         .padding2 = 0, | ||||
|         .padding3 = 0, | ||||
|         .file_type = file_type, | ||||
|         .architecture = switch (builtin.arch) { | ||||
|         .architecture = switch (builtin.cpu.arch) { | ||||
|             .i386 => .x86, | ||||
|             .x86_64 => .AMD_64, | ||||
|             else => unreachable, | ||||
|  | @ -563,62 +563,62 @@ test "init" { | |||
|     const is_32_bit = @bitSizeOf(usize) == 32; | ||||
|     var data = try testInitData(testing.allocator, section_name, string_section_name, .Executable, 0, 0, 123, 789, 456, 012); | ||||
|     defer testing.allocator.free(data); | ||||
|     const elf = try Elf.init(data, builtin.arch, testing.allocator); | ||||
|     const elf = try Elf.init(data, builtin.cpu.arch, testing.allocator); | ||||
|     defer elf.deinit(); | ||||
| 
 | ||||
|     testing.expectEqual(elf.header.data_size, if (is_32_bit) .ThirtyTwoBit else .SixtyFourBit); | ||||
|     testing.expectEqual(elf.header.file_type, .Executable); | ||||
|     testing.expectEqual(elf.header.architecture, switch (builtin.arch) { | ||||
|     try testing.expectEqual(elf.header.data_size, if (is_32_bit) .ThirtyTwoBit else .SixtyFourBit); | ||||
|     try testing.expectEqual(elf.header.file_type, .Executable); | ||||
|     try testing.expectEqual(elf.header.architecture, switch (builtin.cpu.arch) { | ||||
|         .i386 => .x86, | ||||
|         .x86_64 => .AMD_64, | ||||
|         else => unreachable, | ||||
|     }); | ||||
|     testing.expectEqual(elf.header.entry_address, 0); | ||||
|     testing.expectEqual(elf.header.flags, 0); | ||||
|     testing.expectEqual(elf.header.section_name_index, 1); | ||||
|     try testing.expectEqual(elf.header.entry_address, 0); | ||||
|     try testing.expectEqual(elf.header.flags, 0); | ||||
|     try testing.expectEqual(elf.header.section_name_index, 1); | ||||
| 
 | ||||
|     testing.expectEqual(elf.program_headers.len, 0); | ||||
|     try testing.expectEqual(elf.program_headers.len, 0); | ||||
| 
 | ||||
|     testing.expectEqual(elf.section_headers.len, 2); | ||||
|     try testing.expectEqual(elf.section_headers.len, 2); | ||||
|     const section_one = elf.section_headers[0]; | ||||
|     testing.expectEqual(@as(u32, 0), section_one.name_offset); | ||||
|     testing.expectEqual(SectionType.ProgramData, section_one.section_type); | ||||
|     testing.expectEqual(@as(usize, 123), section_one.flags); | ||||
|     testing.expectEqual(@as(usize, 456), section_one.virtual_address); | ||||
|     try testing.expectEqual(@as(u32, 0), section_one.name_offset); | ||||
|     try testing.expectEqual(SectionType.ProgramData, section_one.section_type); | ||||
|     try testing.expectEqual(@as(usize, 123), section_one.flags); | ||||
|     try testing.expectEqual(@as(usize, 456), section_one.virtual_address); | ||||
| 
 | ||||
|     const section_two = elf.section_headers[1]; | ||||
|     testing.expectEqual(section_name.len + 1, section_two.name_offset); | ||||
|     testing.expectEqual(SectionType.StringTable, section_two.section_type); | ||||
|     testing.expectEqual(@as(usize, 789), section_two.flags); | ||||
|     testing.expectEqual(@as(usize, 012), section_two.virtual_address); | ||||
|     try testing.expectEqual(section_name.len + 1, section_two.name_offset); | ||||
|     try testing.expectEqual(SectionType.StringTable, section_two.section_type); | ||||
|     try testing.expectEqual(@as(usize, 789), section_two.flags); | ||||
|     try testing.expectEqual(@as(usize, 012), section_two.virtual_address); | ||||
| 
 | ||||
|     testing.expectEqual(@as(usize, 2), elf.section_data.len); | ||||
|     testing.expectEqual(elf.section_headers[0].size, elf.section_data[0].?.len); | ||||
|     try testing.expectEqual(@as(usize, 2), elf.section_data.len); | ||||
|     try testing.expectEqual(elf.section_headers[0].size, elf.section_data[0].?.len); | ||||
|     for ("some_section" ++ [_]u8{0} ++ "strings" ++ [_]u8{0}) |char, i| { | ||||
|         testing.expectEqual(char, elf.section_data[1].?[i]); | ||||
|         try testing.expectEqual(char, elf.section_data[1].?[i]); | ||||
|     } | ||||
| 
 | ||||
|     // Test the string section having the wrong type | ||||
|     var section_header = elf.section_headers[1]; | ||||
|     section_header.section_type = .ProgramData; | ||||
|     testSetSection(data, section_header, 1); | ||||
|     testing.expectError(Error.WrongStringTableIndex, Elf.init(data, builtin.arch, testing.allocator)); | ||||
|     try testing.expectError(Error.WrongStringTableIndex, Elf.init(data, builtin.cpu.arch, testing.allocator)); | ||||
|     testSetSection(data, elf.section_headers[1], 1); | ||||
| 
 | ||||
|     // Test the section_name_index being out of bounds | ||||
|     var header = elf.header; | ||||
|     header.section_name_index = 3; | ||||
|     testSetHeader(data, header); | ||||
|     testing.expectError(Error.WrongStringTableIndex, Elf.init(data, builtin.arch, testing.allocator)); | ||||
|     try testing.expectError(Error.WrongStringTableIndex, Elf.init(data, builtin.cpu.arch, testing.allocator)); | ||||
| 
 | ||||
|     // Test incorrect endianness | ||||
|     header = elf.header; | ||||
|     header.endianness = switch (builtin.arch.endian()) { | ||||
|     header.endianness = switch (builtin.cpu.arch.endian()) { | ||||
|         .Big => .Little, | ||||
|         .Little => .Big, | ||||
|     }; | ||||
|     testSetHeader(data, header); | ||||
|     testing.expectError(Error.InvalidEndianness, Elf.init(data, builtin.arch, testing.allocator)); | ||||
|     try testing.expectError(Error.InvalidEndianness, Elf.init(data, builtin.cpu.arch, testing.allocator)); | ||||
| 
 | ||||
|     // Test invalid data size | ||||
|     header.data_size = switch (@bitSizeOf(usize)) { | ||||
|  | @ -626,20 +626,20 @@ test "init" { | |||
|         else => .ThirtyTwoBit, | ||||
|     }; | ||||
|     testSetHeader(data, header); | ||||
|     testing.expectError(Error.InvalidDataSize, Elf.init(data, builtin.arch, testing.allocator)); | ||||
|     try testing.expectError(Error.InvalidDataSize, Elf.init(data, builtin.cpu.arch, testing.allocator)); | ||||
| 
 | ||||
|     // Test invalid architecture | ||||
|     header.architecture = switch (builtin.arch) { | ||||
|     header.architecture = switch (builtin.cpu.arch) { | ||||
|         .x86_64 => .Aarch64, | ||||
|         else => .AMD_64, | ||||
|     }; | ||||
|     testSetHeader(data, header); | ||||
|     testing.expectError(Error.InvalidArchitecture, Elf.init(data, builtin.arch, testing.allocator)); | ||||
|     try testing.expectError(Error.InvalidArchitecture, Elf.init(data, builtin.cpu.arch, testing.allocator)); | ||||
| 
 | ||||
|     // Test incorrect magic number | ||||
|     header.magic_number = 123; | ||||
|     testSetHeader(data, header); | ||||
|     testing.expectError(Error.InvalidMagicNumber, Elf.init(data, builtin.arch, testing.allocator)); | ||||
|     try testing.expectError(Error.InvalidMagicNumber, Elf.init(data, builtin.cpu.arch, testing.allocator)); | ||||
| } | ||||
| 
 | ||||
| test "getName" { | ||||
|  | @ -648,26 +648,23 @@ test "getName" { | |||
|     var string_section_name = "strings"; | ||||
|     const data = try testInitData(testing.allocator, section_name, string_section_name, .Executable, 0, undefined, undefined, undefined, undefined, undefined); | ||||
|     defer testing.allocator.free(data); | ||||
|     const elf = try Elf.init(data, builtin.arch, testing.allocator); | ||||
|     const elf = try Elf.init(data, builtin.cpu.arch, testing.allocator); | ||||
|     defer elf.deinit(); | ||||
|     testing.expectEqualSlices(u8, elf.section_headers[0].getName(elf), section_name); | ||||
|     testing.expectEqualSlices(u8, elf.section_headers[1].getName(elf), string_section_name); | ||||
|     try testing.expectEqualSlices(u8, elf.section_headers[0].getName(elf), section_name); | ||||
|     try testing.expectEqualSlices(u8, elf.section_headers[1].getName(elf), string_section_name); | ||||
| } | ||||
| 
 | ||||
| test "toNumBits" { | ||||
|     testing.expectEqual(DataSize.ThirtyTwoBit.toNumBits(), 32); | ||||
|     testing.expectEqual(DataSize.SixtyFourBit.toNumBits(), 64); | ||||
|     try testing.expectEqual(DataSize.ThirtyTwoBit.toNumBits(), 32); | ||||
|     try testing.expectEqual(DataSize.SixtyFourBit.toNumBits(), 64); | ||||
| } | ||||
| 
 | ||||
| test "toEndian" { | ||||
|     testing.expectEqual(Endianness.Little.toEndian(), Endian.Little); | ||||
|     testing.expectEqual(Endianness.Big.toEndian(), Endian.Big); | ||||
|     try testing.expectEqual(Endianness.Little.toEndian(), Endian.Little); | ||||
|     try testing.expectEqual(Endianness.Big.toEndian(), Endian.Big); | ||||
| } | ||||
| 
 | ||||
| test "toArch" { | ||||
|     const known_architectures = [_]Architecture{ .Sparc, .x86, .MIPS, .PowerPC, .PowerPC_64, .ARM, .AMD_64, .Aarch64, .RISC_V }; | ||||
|     const known_archs = [known_architectures.len]Arch{ .sparc, .i386, .mips, .powerpc, .powerpc64, .arm, .x86_64, .aarch64, .riscv32 }; | ||||
| 
 | ||||
|     inline for (@typeInfo(Architecture).Enum.fields) |field| { | ||||
|         const architecture = @field(Architecture, field.name); | ||||
| 
 | ||||
|  | @ -677,9 +674,9 @@ test "toArch" { | |||
|         }; | ||||
| 
 | ||||
|         if (!is_known) { | ||||
|             testing.expectError(Error.UnknownArchitecture, architecture.toArch()); | ||||
|             try testing.expectError(Error.UnknownArchitecture, architecture.toArch()); | ||||
|         } else { | ||||
|             testing.expectEqual(architecture.toArch(), switch (architecture) { | ||||
|             try testing.expectEqual(architecture.toArch(), switch (architecture) { | ||||
|                 .Sparc => .sparc, | ||||
|                 .x86 => .i386, | ||||
|                 .MIPS => .mips, | ||||
|  | @ -696,11 +693,9 @@ test "toArch" { | |||
| } | ||||
| 
 | ||||
| test "hasData" { | ||||
|     const no_data = [_]SectionType{ .Unused, .ProgramSpace, .Reserved }; | ||||
| 
 | ||||
|     inline for (@typeInfo(SectionType).Enum.fields) |field| { | ||||
|         const sec_type = @field(SectionType, field.name); | ||||
|         const should_not_have_data = sec_type == .Unused or sec_type == .ProgramSpace or sec_type == .Reserved; | ||||
|         testing.expectEqual(should_not_have_data, !sec_type.hasData()); | ||||
|         try testing.expectEqual(should_not_have_data, !sec_type.hasData()); | ||||
|     } | ||||
| } | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,13 +1,12 @@ | |||
| const std = @import("std"); | ||||
| const builtin = @import("builtin"); | ||||
| const is_test = builtin.is_test; | ||||
| const is_test = std.builtin.is_test; | ||||
| const expect = std.testing.expect; | ||||
| const expectEqual = std.testing.expectEqual; | ||||
| const expectError = std.testing.expectError; | ||||
| const expectEqualSlices = std.testing.expectEqualSlices; | ||||
| const log = std.log.scoped(.initrd); | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.mock_path; | ||||
| const Allocator = std.mem.Allocator; | ||||
| const AutoHashMap = std.AutoHashMap; | ||||
| const vfs = @import("vfs.zig"); | ||||
|  | @ -43,7 +42,7 @@ pub const InitrdFS = struct { | |||
|     fs: *vfs.FileSystem, | ||||
| 
 | ||||
|     /// The allocator used for allocating memory for opening files. | ||||
|     allocator: *Allocator, | ||||
|     allocator: Allocator, | ||||
| 
 | ||||
|     /// The list of files in the ram disk. These will be pointers into the raw ramdisk to save on | ||||
|     /// allocations. | ||||
|  | @ -67,7 +66,7 @@ pub const InitrdFS = struct { | |||
|         var self = @fieldParentPtr(InitrdFS, "instance", fs.instance); | ||||
|         // As close can't error, if provided with a invalid Node that isn't opened or try to close | ||||
|         // the same file twice, will just do nothing. | ||||
|         if (self.opened_files.remove(node)) |entry_node| { | ||||
|         if (self.opened_files.remove(node)) { | ||||
|             self.allocator.destroy(node); | ||||
|         } | ||||
|     } | ||||
|  | @ -84,12 +83,19 @@ pub const InitrdFS = struct { | |||
| 
 | ||||
|     /// See vfs.FileSystem.write | ||||
|     fn write(fs: *const vfs.FileSystem, node: *const vfs.FileNode, bytes: []const u8) (Allocator.Error || vfs.Error)!usize { | ||||
|         // Suppress unused var warning | ||||
|         _ = fs; | ||||
|         _ = node; | ||||
|         _ = bytes; | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     /// See vfs.FileSystem.open | ||||
|     fn open(fs: *const vfs.FileSystem, dir: *const vfs.DirNode, name: []const u8, flags: vfs.OpenFlags, args: vfs.OpenArgs) (Allocator.Error || vfs.Error)!*vfs.Node { | ||||
|         var self = @fieldParentPtr(InitrdFS, "instance", fs.instance); | ||||
|         // Suppress unused var warning | ||||
|         _ = args; | ||||
|         _ = dir; | ||||
|         switch (flags) { | ||||
|             .CREATE_DIR, .CREATE_FILE, .CREATE_SYMLINK => return vfs.Error.InvalidFlags, | ||||
|             .NO_CREATION => { | ||||
|  | @ -135,7 +141,7 @@ pub const InitrdFS = struct { | |||
|     /// | ||||
|     /// Arguments: | ||||
|     ///     IN stream: *std.io.FixedBufferStream([]u8) - The stream that contains the raw ramdisk data. | ||||
|     ///     IN allocator: *Allocator - The allocator used for initialising any memory needed. | ||||
|     ///     IN allocator: Allocator - The allocator used for initialising any memory needed. | ||||
|     /// | ||||
|     /// Return: *InitrdFS | ||||
|     ///     A pointer to the ram disk file system. | ||||
|  | @ -150,7 +156,7 @@ pub const InitrdFS = struct { | |||
|     ///     error.OutOfMemory    - If there isn't enough memory for initialisation. Any memory | ||||
|     ///                            allocated will be freed. | ||||
|     /// | ||||
|     pub fn init(stream: *std.io.FixedBufferStream([]u8), allocator: *Allocator) (Error || error{EndOfStream} || Allocator.Error)!*InitrdFS { | ||||
|     pub fn init(stream: *std.io.FixedBufferStream([]u8), allocator: Allocator) (Error || error{EndOfStream} || Allocator.Error)!*InitrdFS { | ||||
|         log.info("Init\n", .{}); | ||||
|         defer log.info("Done\n", .{}); | ||||
| 
 | ||||
|  | @ -237,15 +243,17 @@ pub const InitrdFS = struct { | |||
| /// three files: test1.txt, test2.txt and test3.txt. | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *Allocator - The allocator to alloc the raw ramdisk. | ||||
| ///     IN allocator: Allocator - The allocator to alloc the raw ramdisk. | ||||
| /// | ||||
| /// Return: []u8 | ||||
| ///     The bytes of the raw ramdisk in memory. | ||||
| /// | ||||
| /// Error: Allocator.Error | ||||
| ///     error.OutOfMemory - If there isn't enough memory for the in memory ramdisk. | ||||
| ///     FixedBufferStream.WriterError - Writing to the fixed buffer stream failed | ||||
| ///     error.TestExpectedEqual - An equality test failed | ||||
| /// | ||||
| fn createInitrd(allocator: *Allocator) (Allocator.Error || std.io.FixedBufferStream([]u8).WriteError)![]u8 { | ||||
| fn createInitrd(allocator: Allocator) ![]u8 { | ||||
|     // Create 3 valid ramdisk files in memory | ||||
|     const file_names = [_][]const u8{ "test1.txt", "test2.txt", "test3.txt" }; | ||||
|     const file_contents = [_][]const u8{ "This is a test", "This is a test: part 2", "This is a test: the prequel" }; | ||||
|  | @ -275,8 +283,8 @@ fn createInitrd(allocator: *Allocator) (Allocator.Error || std.io.FixedBufferStr | |||
|         try ramdisk_stream.writer().writeAll(file_contents[i]); | ||||
|     } | ||||
|     // Make sure we are full | ||||
|     expectEqual(try ramdisk_stream.getPos(), total_ramdisk_len); | ||||
|     expectEqual(try ramdisk_stream.getPos(), try ramdisk_stream.getEndPos()); | ||||
|     try expectEqual(try ramdisk_stream.getPos(), total_ramdisk_len); | ||||
|     try expectEqual(try ramdisk_stream.getPos(), try ramdisk_stream.getEndPos()); | ||||
|     return ramdisk_bytes; | ||||
| } | ||||
| 
 | ||||
|  | @ -288,24 +296,24 @@ test "init with files valid" { | |||
|     var fs = try InitrdFS.init(&initrd_stream, std.testing.allocator); | ||||
|     defer fs.deinit(); | ||||
| 
 | ||||
|     expectEqual(fs.files.len, 3); | ||||
|     expectEqualSlices(u8, fs.files[0].name, "test1.txt"); | ||||
|     expectEqualSlices(u8, fs.files[1].content, "This is a test: part 2"); | ||||
|     expectEqual(fs.opened_files.count(), 0); | ||||
|     try expectEqual(fs.files.len, 3); | ||||
|     try expectEqualSlices(u8, fs.files[0].name, "test1.txt"); | ||||
|     try expectEqualSlices(u8, fs.files[1].content, "This is a test: part 2"); | ||||
|     try expectEqual(fs.opened_files.count(), 0); | ||||
| } | ||||
| 
 | ||||
| test "init with files invalid - invalid number of files" { | ||||
|     var ramdisk_bytes = try createInitrd(std.testing.allocator); | ||||
|     // Override the number of files | ||||
|     std.mem.writeIntSlice(usize, ramdisk_bytes[0..], 10, builtin.endian); | ||||
|     std.mem.writeIntSlice(usize, ramdisk_bytes[0..], 10, builtin.cpu.arch.endian()); | ||||
|     defer std.testing.allocator.free(ramdisk_bytes); | ||||
| 
 | ||||
|     var initrd_stream = std.io.fixedBufferStream(ramdisk_bytes); | ||||
|     expectError(error.InvalidRamDisk, InitrdFS.init(&initrd_stream, std.testing.allocator)); | ||||
|     try expectError(error.InvalidRamDisk, InitrdFS.init(&initrd_stream, std.testing.allocator)); | ||||
| 
 | ||||
|     // Override the number of files | ||||
|     std.mem.writeIntSlice(usize, ramdisk_bytes[0..], 0, builtin.endian); | ||||
|     expectError(error.InvalidRamDisk, InitrdFS.init(&initrd_stream, std.testing.allocator)); | ||||
|     std.mem.writeIntSlice(usize, ramdisk_bytes[0..], 0, builtin.cpu.arch.endian()); | ||||
|     try expectError(error.InvalidRamDisk, InitrdFS.init(&initrd_stream, std.testing.allocator)); | ||||
| } | ||||
| 
 | ||||
| test "init with files invalid - mix - bad" { | ||||
|  | @ -316,23 +324,23 @@ test "init with files invalid - mix - bad" { | |||
|     { | ||||
|         var ramdisk_bytes = try createInitrd(std.testing.allocator); | ||||
|         // Override the first file name length, make is shorter | ||||
|         std.mem.writeIntSlice(usize, ramdisk_bytes[4..], 2, builtin.endian); | ||||
|         std.mem.writeIntSlice(usize, ramdisk_bytes[4..], 2, builtin.cpu.arch.endian()); | ||||
|         defer std.testing.allocator.free(ramdisk_bytes); | ||||
| 
 | ||||
|         var initrd_stream = std.io.fixedBufferStream(ramdisk_bytes); | ||||
|         expectError(error.InvalidRamDisk, InitrdFS.init(&initrd_stream, std.testing.allocator)); | ||||
|         try expectError(error.InvalidRamDisk, InitrdFS.init(&initrd_stream, std.testing.allocator)); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|         var ramdisk_bytes = try createInitrd(std.testing.allocator); | ||||
|         // Override the first file name length, make is 4 shorter | ||||
|         std.mem.writeIntSlice(usize, ramdisk_bytes[4..], 5, builtin.endian); | ||||
|         std.mem.writeIntSlice(usize, ramdisk_bytes[4..], 5, builtin.cpu.arch.endian()); | ||||
|         // Override the second file name length, make is 4 longer | ||||
|         std.mem.writeIntSlice(usize, ramdisk_bytes[35..], 13, builtin.endian); | ||||
|         std.mem.writeIntSlice(usize, ramdisk_bytes[35..], 13, builtin.cpu.arch.endian()); | ||||
|         defer std.testing.allocator.free(ramdisk_bytes); | ||||
| 
 | ||||
|         var initrd_stream = std.io.fixedBufferStream(ramdisk_bytes); | ||||
|         expectError(error.InvalidRamDisk, InitrdFS.init(&initrd_stream, std.testing.allocator)); | ||||
|         try expectError(error.InvalidRamDisk, InitrdFS.init(&initrd_stream, std.testing.allocator)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -348,7 +356,7 @@ test "init with files cleans memory if OutOfMemory" { | |||
|         defer std.testing.allocator.free(ramdisk_bytes); | ||||
| 
 | ||||
|         var initrd_stream = std.io.fixedBufferStream(ramdisk_bytes); | ||||
|         expectError(error.OutOfMemory, InitrdFS.init(&initrd_stream, &fa.allocator)); | ||||
|         try expectError(error.OutOfMemory, InitrdFS.init(&initrd_stream, fa.allocator())); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -360,7 +368,7 @@ test "getRootNode" { | |||
|     var fs = try InitrdFS.init(&initrd_stream, std.testing.allocator); | ||||
|     defer fs.deinit(); | ||||
| 
 | ||||
|     expectEqual(fs.fs.getRootNode(fs.fs), &fs.root_node.Dir); | ||||
|     try expectEqual(fs.fs.getRootNode(fs.fs), &fs.root_node.Dir); | ||||
| } | ||||
| 
 | ||||
| test "open valid file" { | ||||
|  | @ -376,21 +384,21 @@ test "open valid file" { | |||
|     var file1 = try vfs.openFile("/test1.txt", .NO_CREATION); | ||||
|     defer file1.close(); | ||||
| 
 | ||||
|     expectEqual(fs.opened_files.count(), 1); | ||||
|     expectEqualSlices(u8, fs.opened_files.get(@ptrCast(*const vfs.Node, file1)).?.name, "test1.txt"); | ||||
|     try expectEqual(fs.opened_files.count(), 1); | ||||
|     try expectEqualSlices(u8, fs.opened_files.get(@ptrCast(*const vfs.Node, file1)).?.name, "test1.txt"); | ||||
| 
 | ||||
|     var file3_node = try vfs.open("/test3.txt", true, .NO_CREATION, .{}); | ||||
|     defer file3_node.File.close(); | ||||
| 
 | ||||
|     expectEqual(fs.opened_files.count(), 2); | ||||
|     expectEqualSlices(u8, fs.opened_files.get(file3_node).?.content, "This is a test: the prequel"); | ||||
|     try expectEqual(fs.opened_files.count(), 2); | ||||
|     try expectEqualSlices(u8, fs.opened_files.get(file3_node).?.content, "This is a test: the prequel"); | ||||
| 
 | ||||
|     var dir1 = try vfs.openDir("/", .NO_CREATION); | ||||
|     expectEqual(&fs.root_node.Dir, dir1); | ||||
|     try expectEqual(&fs.root_node.Dir, dir1); | ||||
|     var file2 = &(try dir1.open("test2.txt", .NO_CREATION, .{})).File; | ||||
|     defer file2.close(); | ||||
| 
 | ||||
|     expectEqual(fs.opened_files.count(), 3); | ||||
|     try expectEqual(fs.opened_files.count(), 3); | ||||
| } | ||||
| 
 | ||||
| test "open fail with invalid flags" { | ||||
|  | @ -403,21 +411,21 @@ test "open fail with invalid flags" { | |||
| 
 | ||||
|     try vfs.setRoot(fs.root_node); | ||||
| 
 | ||||
|     expectError(error.InvalidFlags, vfs.openFile("/text10.txt", .CREATE_DIR)); | ||||
|     expectError(error.InvalidFlags, vfs.openFile("/text10.txt", .CREATE_FILE)); | ||||
|     expectError(error.InvalidFlags, vfs.openFile("/text10.txt", .CREATE_SYMLINK)); | ||||
|     expectError(error.InvalidFlags, vfs.openDir("/text10.txt", .CREATE_DIR)); | ||||
|     expectError(error.InvalidFlags, vfs.openDir("/text10.txt", .CREATE_FILE)); | ||||
|     expectError(error.InvalidFlags, vfs.openDir("/text10.txt", .CREATE_SYMLINK)); | ||||
|     expectError(error.InvalidFlags, vfs.openFile("/test/", .CREATE_DIR)); | ||||
|     expectError(error.InvalidFlags, vfs.openFile("/test/", .CREATE_FILE)); | ||||
|     expectError(error.InvalidFlags, vfs.openFile("/test/", .CREATE_SYMLINK)); | ||||
|     expectError(error.InvalidFlags, vfs.openDir("/test/", .CREATE_DIR)); | ||||
|     expectError(error.InvalidFlags, vfs.openDir("/test/", .CREATE_FILE)); | ||||
|     expectError(error.InvalidFlags, vfs.openDir("/test/", .CREATE_SYMLINK)); | ||||
|     expectError(error.InvalidFlags, vfs.openSymlink("/test/", "", .CREATE_FILE)); | ||||
|     expectError(error.InvalidFlags, vfs.openSymlink("/test/", "", .CREATE_DIR)); | ||||
|     expectError(error.InvalidFlags, vfs.openSymlink("/test/", "", .CREATE_SYMLINK)); | ||||
|     try expectError(error.InvalidFlags, vfs.openFile("/text10.txt", .CREATE_DIR)); | ||||
|     try expectError(error.InvalidFlags, vfs.openFile("/text10.txt", .CREATE_FILE)); | ||||
|     try expectError(error.InvalidFlags, vfs.openFile("/text10.txt", .CREATE_SYMLINK)); | ||||
|     try expectError(error.InvalidFlags, vfs.openDir("/text10.txt", .CREATE_DIR)); | ||||
|     try expectError(error.InvalidFlags, vfs.openDir("/text10.txt", .CREATE_FILE)); | ||||
|     try expectError(error.InvalidFlags, vfs.openDir("/text10.txt", .CREATE_SYMLINK)); | ||||
|     try expectError(error.InvalidFlags, vfs.openFile("/test/", .CREATE_DIR)); | ||||
|     try expectError(error.InvalidFlags, vfs.openFile("/test/", .CREATE_FILE)); | ||||
|     try expectError(error.InvalidFlags, vfs.openFile("/test/", .CREATE_SYMLINK)); | ||||
|     try expectError(error.InvalidFlags, vfs.openDir("/test/", .CREATE_DIR)); | ||||
|     try expectError(error.InvalidFlags, vfs.openDir("/test/", .CREATE_FILE)); | ||||
|     try expectError(error.InvalidFlags, vfs.openDir("/test/", .CREATE_SYMLINK)); | ||||
|     try expectError(error.InvalidFlags, vfs.openSymlink("/test/", "", .CREATE_FILE)); | ||||
|     try expectError(error.InvalidFlags, vfs.openSymlink("/test/", "", .CREATE_DIR)); | ||||
|     try expectError(error.InvalidFlags, vfs.openSymlink("/test/", "", .CREATE_SYMLINK)); | ||||
| } | ||||
| 
 | ||||
| test "open fail with NoSuchFileOrDir" { | ||||
|  | @ -429,8 +437,8 @@ test "open fail with NoSuchFileOrDir" { | |||
|     defer fs.deinit(); | ||||
| 
 | ||||
|     try vfs.setRoot(fs.root_node); | ||||
|     expectError(error.NoSuchFileOrDir, vfs.openFile("/text10.txt", .NO_CREATION)); | ||||
|     expectError(error.NoSuchFileOrDir, vfs.openDir("/temp/", .NO_CREATION)); | ||||
|     try expectError(error.NoSuchFileOrDir, vfs.openFile("/text10.txt", .NO_CREATION)); | ||||
|     try expectError(error.NoSuchFileOrDir, vfs.openDir("/temp/", .NO_CREATION)); | ||||
| } | ||||
| 
 | ||||
| test "open a file, out of memory" { | ||||
|  | @ -440,12 +448,12 @@ test "open a file, out of memory" { | |||
|     defer std.testing.allocator.free(ramdisk_bytes); | ||||
| 
 | ||||
|     var initrd_stream = std.io.fixedBufferStream(ramdisk_bytes); | ||||
|     var fs = try InitrdFS.init(&initrd_stream, &fa.allocator); | ||||
|     var fs = try InitrdFS.init(&initrd_stream, fa.allocator()); | ||||
|     defer fs.deinit(); | ||||
| 
 | ||||
|     try vfs.setRoot(fs.root_node); | ||||
| 
 | ||||
|     expectError(error.OutOfMemory, vfs.openFile("/test1.txt", .NO_CREATION)); | ||||
|     try expectError(error.OutOfMemory, vfs.openFile("/test1.txt", .NO_CREATION)); | ||||
| } | ||||
| 
 | ||||
| test "open two of the same file" { | ||||
|  | @ -464,14 +472,14 @@ test "open two of the same file" { | |||
|     const file2 = try vfs.openFile("/test1.txt", .NO_CREATION); | ||||
|     defer file2.close(); | ||||
| 
 | ||||
|     expectEqual(fs.opened_files.count(), 2); | ||||
|     expect(file1 != file2); | ||||
|     try expectEqual(fs.opened_files.count(), 2); | ||||
|     try expect(file1 != file2); | ||||
| 
 | ||||
|     var b1: [128]u8 = undefined; | ||||
|     const length1 = try file1.read(b1[0..b1.len]); | ||||
|     var b2: [128]u8 = undefined; | ||||
|     const length2 = try file2.read(b2[0..b2.len]); | ||||
|     expectEqualSlices(u8, b1[0..length1], b2[0..length2]); | ||||
|     try expectEqualSlices(u8, b1[0..length1], b2[0..length2]); | ||||
| } | ||||
| 
 | ||||
| test "close a file" { | ||||
|  | @ -486,24 +494,22 @@ test "close a file" { | |||
| 
 | ||||
|     var file1 = try vfs.openFile("/test1.txt", .NO_CREATION); | ||||
| 
 | ||||
|     var file1_node = @ptrCast(*const vfs.Node, file1); | ||||
| 
 | ||||
|     expectEqual(fs.opened_files.count(), 1); | ||||
|     try expectEqual(fs.opened_files.count(), 1); | ||||
| 
 | ||||
|     var file3_node = try vfs.open("/test3.txt", true, .NO_CREATION, .{}); | ||||
| 
 | ||||
|     expectEqual(fs.opened_files.count(), 2); | ||||
|     try expectEqual(fs.opened_files.count(), 2); | ||||
|     file1.close(); | ||||
|     expectEqual(fs.opened_files.count(), 1); | ||||
|     try expectEqual(fs.opened_files.count(), 1); | ||||
| 
 | ||||
|     var dir1 = try vfs.openDir("/", .NO_CREATION); | ||||
|     expectEqual(&fs.root_node.Dir, dir1); | ||||
|     try expectEqual(&fs.root_node.Dir, dir1); | ||||
|     var file2 = &(try dir1.open("test2.txt", .NO_CREATION, .{})).File; | ||||
|     defer file2.close(); | ||||
| 
 | ||||
|     expectEqual(fs.opened_files.count(), 2); | ||||
|     try expectEqual(fs.opened_files.count(), 2); | ||||
|     file3_node.File.close(); | ||||
|     expectEqual(fs.opened_files.count(), 1); | ||||
|     try expectEqual(fs.opened_files.count(), 1); | ||||
| } | ||||
| 
 | ||||
| test "close a non-opened file" { | ||||
|  | @ -521,7 +527,7 @@ test "close a non-opened file" { | |||
|     defer file1.close(); | ||||
| 
 | ||||
|     // Only one file open | ||||
|     expectEqual(fs.opened_files.count(), 1); | ||||
|     try expectEqual(fs.opened_files.count(), 1); | ||||
| 
 | ||||
|     // Craft a Node | ||||
|     var fake_node = try std.testing.allocator.create(vfs.Node); | ||||
|  | @ -530,7 +536,7 @@ test "close a non-opened file" { | |||
|     fake_node.File.close(); | ||||
| 
 | ||||
|     // Still only one file open | ||||
|     expectEqual(fs.opened_files.count(), 1); | ||||
|     try expectEqual(fs.opened_files.count(), 1); | ||||
| } | ||||
| 
 | ||||
| test "read a file" { | ||||
|  | @ -549,12 +555,12 @@ test "read a file" { | |||
|     var bytes1: [128]u8 = undefined; | ||||
|     const length1 = try file1.read(bytes1[0..bytes1.len]); | ||||
| 
 | ||||
|     expectEqualSlices(u8, bytes1[0..length1], "This is a test"); | ||||
|     try expectEqualSlices(u8, bytes1[0..length1], "This is a test"); | ||||
| 
 | ||||
|     var bytes2: [5]u8 = undefined; | ||||
|     const length2 = try file1.read(bytes2[0..bytes2.len]); | ||||
| 
 | ||||
|     expectEqualSlices(u8, bytes2[0..length2], "This "); | ||||
|     try expectEqualSlices(u8, bytes2[0..length2], "This "); | ||||
| } | ||||
| 
 | ||||
| test "read a file, invalid/not opened/crafted *const Node" { | ||||
|  | @ -572,7 +578,7 @@ test "read a file, invalid/not opened/crafted *const Node" { | |||
|     defer file1.close(); | ||||
| 
 | ||||
|     // Only one file open | ||||
|     expectEqual(fs.opened_files.count(), 1); | ||||
|     try expectEqual(fs.opened_files.count(), 1); | ||||
| 
 | ||||
|     // Craft a Node | ||||
|     var fake_node = try std.testing.allocator.create(vfs.Node); | ||||
|  | @ -580,10 +586,10 @@ test "read a file, invalid/not opened/crafted *const Node" { | |||
|     fake_node.* = .{ .File = .{ .fs = fs.fs } }; | ||||
| 
 | ||||
|     var unused: [1]u8 = undefined; | ||||
|     expectError(error.NotOpened, fake_node.File.read(unused[0..unused.len])); | ||||
|     try expectError(error.NotOpened, fake_node.File.read(unused[0..unused.len])); | ||||
| 
 | ||||
|     // Still only one file open | ||||
|     expectEqual(fs.opened_files.count(), 1); | ||||
|     try expectEqual(fs.opened_files.count(), 1); | ||||
| } | ||||
| 
 | ||||
| test "write does nothing" { | ||||
|  | @ -600,10 +606,10 @@ test "write does nothing" { | |||
|     var file1 = try vfs.openFile("/test1.txt", .NO_CREATION); | ||||
|     defer file1.close(); | ||||
| 
 | ||||
|     expectEqual(@as(usize, 0), try file1.write("Blah")); | ||||
|     try expectEqual(@as(usize, 0), try file1.write("Blah")); | ||||
| 
 | ||||
|     // Unchanged file content | ||||
|     expectEqualSlices(u8, fs.opened_files.get(@ptrCast(*const vfs.Node, file1)).?.content, "This is a test"); | ||||
|     try expectEqualSlices(u8, fs.opened_files.get(@ptrCast(*const vfs.Node, file1)).?.content, "This is a test"); | ||||
| } | ||||
| 
 | ||||
| /// See std.testing.expectEqualSlices. As need our panic. | ||||
|  | @ -622,10 +628,7 @@ fn expectEqualSlicesClone(comptime T: type, expected: []const T, actual: []const | |||
| /// | ||||
| /// Test that we can open, read and close a file | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *Allocator - The allocator used for reading. | ||||
| /// | ||||
| fn rt_openReadClose(allocator: *Allocator) void { | ||||
| fn rt_openReadClose() void { | ||||
|     const f1 = vfs.openFile("/ramdisk_test1.txt", .NO_CREATION) catch |e| { | ||||
|         panic(@errorReturnTrace(), "FAILURE: Failed to open file: {}\n", .{e}); | ||||
|     }; | ||||
|  | @ -666,7 +669,7 @@ fn runtimeTests(rd_fs: *InitrdFS) void { | |||
|     vfs.setRoot(rd_fs.root_node) catch |e| { | ||||
|         panic(@errorReturnTrace(), "Ramdisk root node isn't a directory node: {}\n", .{e}); | ||||
|     }; | ||||
|     rt_openReadClose(rd_fs.allocator); | ||||
|     rt_openReadClose(); | ||||
|     if (rd_fs.opened_files.count() != 0) { | ||||
|         panic(@errorReturnTrace(), "FAILURE: Didn't close all files\n", .{}); | ||||
|     } | ||||
|  |  | |||
|  | @ -319,7 +319,7 @@ fn traversePath(path: []const u8, follow_symlinks: bool, flags: OpenFlags, args: | |||
| 
 | ||||
|         const Self = @This(); | ||||
| 
 | ||||
|         fn func(split: *std.mem.SplitIterator, node: *Node, follow_links: bool, rec_flags: OpenFlags) (Allocator.Error || Error)!Self { | ||||
|         fn func(split: *std.mem.SplitIterator(u8), node: *Node, follow_links: bool, rec_flags: OpenFlags) (Allocator.Error || Error)!Self { | ||||
|             // Get segment string. This will not be unreachable as we've made sure the spliterator has more segments left | ||||
|             const seg = split.next() orelse unreachable; | ||||
|             if (split.rest().len == 0) { | ||||
|  | @ -347,7 +347,7 @@ fn traversePath(path: []const u8, follow_symlinks: bool, flags: OpenFlags, args: | |||
|     }; | ||||
| 
 | ||||
|     // Split path but skip the first separator character | ||||
|     var split = std.mem.split(path[1..], &[_]u8{SEPARATOR}); | ||||
|     var split = std.mem.split(u8, path[1..], &[_]u8{SEPARATOR}); | ||||
|     // Traverse directories while we're not at the last segment | ||||
|     const result = try TraversalParent.func(&split, root, follow_symlinks, .NO_CREATION); | ||||
| 
 | ||||
|  | @ -569,7 +569,7 @@ const TestFS = struct { | |||
|         data: ?[]u8, | ||||
|         children: *ArrayList(*@This()), | ||||
| 
 | ||||
|         fn deinit(self: *@This(), allocator: *Allocator) void { | ||||
|         fn deinit(self: *@This(), allocator: Allocator) void { | ||||
|             allocator.destroy(self.val); | ||||
|             allocator.free(self.name); | ||||
|             if (self.data) |d| { | ||||
|  | @ -586,7 +586,7 @@ const TestFS = struct { | |||
| 
 | ||||
|     tree: TreeNode, | ||||
|     fs: *FileSystem, | ||||
|     allocator: *Allocator, | ||||
|     allocator: Allocator, | ||||
|     open_count: usize, | ||||
|     instance: usize, | ||||
| 
 | ||||
|  | @ -635,6 +635,8 @@ const TestFS = struct { | |||
|     } | ||||
| 
 | ||||
|     fn close(fs: *const FileSystem, node: *const Node) void { | ||||
|         // Suppress unused var warning | ||||
|         _ = node; | ||||
|         var test_fs = @fieldParentPtr(TestFS, "instance", fs.instance); | ||||
|         test_fs.open_count -= 1; | ||||
|     } | ||||
|  | @ -716,7 +718,7 @@ const TestFS = struct { | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| fn testInitFs(allocator: *Allocator) !*TestFS { | ||||
| fn testInitFs(allocator: Allocator) !*TestFS { | ||||
|     const fs = try allocator.create(FileSystem); | ||||
|     var testfs = try allocator.create(TestFS); | ||||
|     var root_node = try allocator.create(Node); | ||||
|  | @ -754,7 +756,7 @@ test "mount" { | |||
|     var testfs = try testInitFs(allocator); | ||||
|     defer allocator.destroy(testfs); | ||||
|     defer testfs.deinit(); | ||||
|     defer testing.expectEqual(testfs.open_count, 0); | ||||
|     defer testing.expectEqual(testfs.open_count, 0) catch @panic("Test fs open count is not zero\n"); | ||||
| 
 | ||||
|     testfs.instance = 1; | ||||
|     root = testfs.tree.val; | ||||
|  | @ -763,7 +765,7 @@ test "mount" { | |||
|     var testfs2 = try testInitFs(allocator); | ||||
|     defer allocator.destroy(testfs2); | ||||
|     defer testfs2.deinit(); | ||||
|     defer testing.expectEqual(testfs2.open_count, 0); | ||||
|     defer testing.expectEqual(testfs2.open_count, 0) catch @panic("Second test fs open count is not zero\n"); | ||||
| 
 | ||||
|     testfs2.instance = 2; | ||||
|     // Create the dir to mount to | ||||
|  | @ -771,21 +773,21 @@ test "mount" { | |||
|     defer dir.close(); | ||||
|     try mount(dir, testfs2.fs); | ||||
|     defer umount(dir); | ||||
|     testing.expectError(MountError.DirAlreadyMounted, mount(dir, testfs2.fs)); | ||||
|     try testing.expectError(MountError.DirAlreadyMounted, mount(dir, testfs2.fs)); | ||||
| 
 | ||||
|     // Ensure the mount worked | ||||
|     testing.expectEqual((dir.mount orelse unreachable), testfs2.fs.getRootNode(testfs2.fs)); | ||||
|     testing.expectEqual((dir.mount orelse unreachable).fs, testfs2.fs); | ||||
|     try testing.expectEqual((dir.mount orelse unreachable), testfs2.fs.getRootNode(testfs2.fs)); | ||||
|     try testing.expectEqual((dir.mount orelse unreachable).fs, testfs2.fs); | ||||
|     // Create a file within the mounted directory | ||||
|     var test_file = try openFile("/mnt/123.txt", .CREATE_FILE); | ||||
|     defer test_file.close(); | ||||
|     testing.expectEqual(@ptrCast(*const FileSystem, testfs2.fs), test_file.fs); | ||||
|     try testing.expectEqual(@ptrCast(*const FileSystem, testfs2.fs), test_file.fs); | ||||
|     // This shouldn't be in the root fs | ||||
|     testing.expectEqual(@as(usize, 1), testfs.tree.children.items.len); | ||||
|     testing.expectEqual(@as(usize, 0), testfs.tree.children.items[0].children.items.len); | ||||
|     try testing.expectEqual(@as(usize, 1), testfs.tree.children.items.len); | ||||
|     try testing.expectEqual(@as(usize, 0), testfs.tree.children.items[0].children.items.len); | ||||
|     // It should be in the mounted fs | ||||
|     testing.expectEqual(@as(usize, 1), testfs2.tree.children.items.len); | ||||
|     testing.expectEqual(test_file, &testfs2.tree.children.items[0].val.File); | ||||
|     try testing.expectEqual(@as(usize, 1), testfs2.tree.children.items.len); | ||||
|     try testing.expectEqual(test_file, &testfs2.tree.children.items[0].val.File); | ||||
| } | ||||
| 
 | ||||
| test "traversePath" { | ||||
|  | @ -797,11 +799,11 @@ test "traversePath" { | |||
| 
 | ||||
|     // Get the root | ||||
|     var test_root = try traversePath("/", false, .NO_CREATION, .{}); | ||||
|     testing.expectEqual(test_root, root); | ||||
|     try testing.expectEqual(test_root, root); | ||||
|     // Create a file in the root and try to traverse to it | ||||
|     var child1 = try test_root.Dir.open("child1.txt", .CREATE_FILE, .{}); | ||||
|     var child1_traversed = try traversePath("/child1.txt", false, .NO_CREATION, .{}); | ||||
|     testing.expectEqual(child1, child1_traversed); | ||||
|     try testing.expectEqual(child1, child1_traversed); | ||||
|     // Close the open files | ||||
|     child1.File.close(); | ||||
|     child1_traversed.File.close(); | ||||
|  | @ -809,12 +811,12 @@ test "traversePath" { | |||
|     // Same but with a directory | ||||
|     var child2 = try test_root.Dir.open("child2", .CREATE_DIR, .{}); | ||||
|     const child2_traversed = try traversePath("/child2", false, .NO_CREATION, .{}); | ||||
|     testing.expectEqual(child2, child2_traversed); | ||||
|     try testing.expectEqual(child2, child2_traversed); | ||||
| 
 | ||||
|     // Again but with a file within that directory | ||||
|     var child3 = try child2.Dir.open("child3.txt", .CREATE_FILE, .{}); | ||||
|     var child3_traversed = try traversePath("/child2/child3.txt", false, .NO_CREATION, .{}); | ||||
|     testing.expectEqual(child3, child3_traversed); | ||||
|     try testing.expectEqual(child3, child3_traversed); | ||||
|     // Close the open files | ||||
|     child2.Dir.close(); | ||||
|     child2_traversed.Dir.close(); | ||||
|  | @ -823,38 +825,38 @@ test "traversePath" { | |||
|     // Create and open a symlink | ||||
|     var child4 = try traversePath("/child2/link", false, .CREATE_SYMLINK, .{ .symlink_target = "/child2/child3.txt" }); | ||||
|     var child4_linked = try traversePath("/child2/link", true, .NO_CREATION, .{}); | ||||
|     testing.expectEqual(child4_linked, child3); | ||||
|     try testing.expectEqual(child4_linked, child3); | ||||
|     var child5 = try traversePath("/child4", false, .CREATE_SYMLINK, .{ .symlink_target = "/child2" }); | ||||
|     var child5_linked = try traversePath("/child4/child3.txt", true, .NO_CREATION, .{}); | ||||
|     testing.expectEqual(child5_linked, child4_linked); | ||||
|     try testing.expectEqual(child5_linked, child4_linked); | ||||
|     child3.File.close(); | ||||
|     child4.Symlink.close(); | ||||
|     child5.Symlink.close(); | ||||
|     child4_linked.File.close(); | ||||
|     child5_linked.File.close(); | ||||
| 
 | ||||
|     testing.expectError(Error.NotAbsolutePath, traversePath("abc", false, .NO_CREATION, .{})); | ||||
|     testing.expectError(Error.NotAbsolutePath, traversePath("", false, .NO_CREATION, .{})); | ||||
|     testing.expectError(Error.NotAbsolutePath, traversePath("a/", false, .NO_CREATION, .{})); | ||||
|     testing.expectError(Error.NoSuchFileOrDir, traversePath("/notadir/abc.txt", false, .NO_CREATION, .{})); | ||||
|     testing.expectError(Error.NoSuchFileOrDir, traversePath("/ ", false, .NO_CREATION, .{})); | ||||
|     testing.expectError(Error.NotADirectory, traversePath("/child1.txt/abc.txt", false, .NO_CREATION, .{})); | ||||
|     testing.expectError(Error.NoSymlinkTarget, traversePath("/childX.txt", false, .CREATE_SYMLINK, .{})); | ||||
|     try testing.expectError(Error.NotAbsolutePath, traversePath("abc", false, .NO_CREATION, .{})); | ||||
|     try testing.expectError(Error.NotAbsolutePath, traversePath("", false, .NO_CREATION, .{})); | ||||
|     try testing.expectError(Error.NotAbsolutePath, traversePath("a/", false, .NO_CREATION, .{})); | ||||
|     try testing.expectError(Error.NoSuchFileOrDir, traversePath("/notadir/abc.txt", false, .NO_CREATION, .{})); | ||||
|     try testing.expectError(Error.NoSuchFileOrDir, traversePath("/ ", false, .NO_CREATION, .{})); | ||||
|     try testing.expectError(Error.NotADirectory, traversePath("/child1.txt/abc.txt", false, .NO_CREATION, .{})); | ||||
|     try testing.expectError(Error.NoSymlinkTarget, traversePath("/childX.txt", false, .CREATE_SYMLINK, .{})); | ||||
| 
 | ||||
|     // Since we've closed all the files, the open files count should be zero | ||||
|     testing.expectEqual(testfs.open_count, 0); | ||||
|     try testing.expectEqual(testfs.open_count, 0); | ||||
| } | ||||
| 
 | ||||
| test "isAbsolute" { | ||||
|     testing.expect(isAbsolute("/")); | ||||
|     testing.expect(isAbsolute("/abc")); | ||||
|     testing.expect(isAbsolute("/abc/def")); | ||||
|     testing.expect(isAbsolute("/ a bc/de f")); | ||||
|     testing.expect(isAbsolute("//")); | ||||
|     testing.expect(!isAbsolute(" /")); | ||||
|     testing.expect(!isAbsolute("")); | ||||
|     testing.expect(!isAbsolute("abc")); | ||||
|     testing.expect(!isAbsolute("abc/def")); | ||||
|     try testing.expect(isAbsolute("/")); | ||||
|     try testing.expect(isAbsolute("/abc")); | ||||
|     try testing.expect(isAbsolute("/abc/def")); | ||||
|     try testing.expect(isAbsolute("/ a bc/de f")); | ||||
|     try testing.expect(isAbsolute("//")); | ||||
|     try testing.expect(!isAbsolute(" /")); | ||||
|     try testing.expect(!isAbsolute("")); | ||||
|     try testing.expect(!isAbsolute("abc")); | ||||
|     try testing.expect(!isAbsolute("abc/def")); | ||||
| } | ||||
| 
 | ||||
| test "isDir" { | ||||
|  | @ -862,9 +864,9 @@ test "isDir" { | |||
|     const dir = Node{ .Dir = .{ .fs = &fs, .mount = null } }; | ||||
|     const file = Node{ .File = .{ .fs = &fs } }; | ||||
|     const symlink = Node{ .Symlink = .{ .fs = &fs, .path = "" } }; | ||||
|     testing.expect(!symlink.isDir()); | ||||
|     testing.expect(!file.isDir()); | ||||
|     testing.expect(dir.isDir()); | ||||
|     try testing.expect(!symlink.isDir()); | ||||
|     try testing.expect(!file.isDir()); | ||||
|     try testing.expect(dir.isDir()); | ||||
| } | ||||
| 
 | ||||
| test "isFile" { | ||||
|  | @ -872,9 +874,9 @@ test "isFile" { | |||
|     const dir = Node{ .Dir = .{ .fs = &fs, .mount = null } }; | ||||
|     const file = Node{ .File = .{ .fs = &fs } }; | ||||
|     const symlink = Node{ .Symlink = .{ .fs = &fs, .path = "" } }; | ||||
|     testing.expect(!dir.isFile()); | ||||
|     testing.expect(!symlink.isFile()); | ||||
|     testing.expect(file.isFile()); | ||||
|     try testing.expect(!dir.isFile()); | ||||
|     try testing.expect(!symlink.isFile()); | ||||
|     try testing.expect(file.isFile()); | ||||
| } | ||||
| 
 | ||||
| test "isSymlink" { | ||||
|  | @ -882,9 +884,9 @@ test "isSymlink" { | |||
|     const dir = Node{ .Dir = .{ .fs = &fs, .mount = null } }; | ||||
|     const file = Node{ .File = .{ .fs = &fs } }; | ||||
|     const symlink = Node{ .Symlink = .{ .fs = &fs, .path = "" } }; | ||||
|     testing.expect(!dir.isSymlink()); | ||||
|     testing.expect(!file.isSymlink()); | ||||
|     testing.expect(symlink.isSymlink()); | ||||
|     try testing.expect(!dir.isSymlink()); | ||||
|     try testing.expect(!file.isSymlink()); | ||||
|     try testing.expect(symlink.isSymlink()); | ||||
| } | ||||
| 
 | ||||
| test "open" { | ||||
|  | @ -895,46 +897,46 @@ test "open" { | |||
| 
 | ||||
|     // Creating a file | ||||
|     var test_node = try openFile("/abc.txt", .CREATE_FILE); | ||||
|     testing.expectEqual(testfs.tree.children.items.len, 1); | ||||
|     try testing.expectEqual(testfs.tree.children.items.len, 1); | ||||
|     var tree = testfs.tree.children.items[0]; | ||||
|     testing.expect(tree.val.isFile()); | ||||
|     testing.expectEqual(test_node, &tree.val.File); | ||||
|     testing.expect(std.mem.eql(u8, tree.name, "abc.txt")); | ||||
|     testing.expectEqual(tree.data, null); | ||||
|     testing.expectEqual(tree.children.items.len, 0); | ||||
|     try testing.expect(tree.val.isFile()); | ||||
|     try testing.expectEqual(test_node, &tree.val.File); | ||||
|     try testing.expect(std.mem.eql(u8, tree.name, "abc.txt")); | ||||
|     try testing.expectEqual(tree.data, null); | ||||
|     try testing.expectEqual(tree.children.items.len, 0); | ||||
| 
 | ||||
|     // Creating a dir | ||||
|     var test_dir = try openDir("/def", .CREATE_DIR); | ||||
|     testing.expectEqual(testfs.tree.children.items.len, 2); | ||||
|     try testing.expectEqual(testfs.tree.children.items.len, 2); | ||||
|     tree = testfs.tree.children.items[1]; | ||||
|     testing.expect(tree.val.isDir()); | ||||
|     testing.expectEqual(test_dir, &tree.val.Dir); | ||||
|     testing.expect(std.mem.eql(u8, tree.name, "def")); | ||||
|     testing.expectEqual(tree.data, null); | ||||
|     testing.expectEqual(tree.children.items.len, 0); | ||||
|     try testing.expect(tree.val.isDir()); | ||||
|     try testing.expectEqual(test_dir, &tree.val.Dir); | ||||
|     try testing.expect(std.mem.eql(u8, tree.name, "def")); | ||||
|     try testing.expectEqual(tree.data, null); | ||||
|     try testing.expectEqual(tree.children.items.len, 0); | ||||
| 
 | ||||
|     // Creating a file under a new dir | ||||
|     test_node = try openFile("/def/ghi.zig", .CREATE_FILE); | ||||
|     testing.expectEqual(testfs.tree.children.items[1].children.items.len, 1); | ||||
|     try testing.expectEqual(testfs.tree.children.items[1].children.items.len, 1); | ||||
|     tree = testfs.tree.children.items[1].children.items[0]; | ||||
|     testing.expect(tree.val.isFile()); | ||||
|     testing.expectEqual(test_node, &tree.val.File); | ||||
|     testing.expect(std.mem.eql(u8, tree.name, "ghi.zig")); | ||||
|     testing.expectEqual(tree.data, null); | ||||
|     testing.expectEqual(tree.children.items.len, 0); | ||||
|     try testing.expect(tree.val.isFile()); | ||||
|     try testing.expectEqual(test_node, &tree.val.File); | ||||
|     try testing.expect(std.mem.eql(u8, tree.name, "ghi.zig")); | ||||
|     try testing.expectEqual(tree.data, null); | ||||
|     try testing.expectEqual(tree.children.items.len, 0); | ||||
| 
 | ||||
|     testing.expectError(Error.NoSuchFileOrDir, openDir("/jkl", .NO_CREATION)); | ||||
|     testing.expectError(Error.NoSuchFileOrDir, openFile("/mno.txt", .NO_CREATION)); | ||||
|     testing.expectError(Error.NoSuchFileOrDir, openFile("/def/pqr.txt", .NO_CREATION)); | ||||
|     testing.expectError(Error.NoSuchFileOrDir, openDir("/mno/stu", .NO_CREATION)); | ||||
|     testing.expectError(Error.NoSuchFileOrDir, openFile("/mno/stu.txt", .NO_CREATION)); | ||||
|     testing.expectError(Error.NotADirectory, openFile("/abc.txt/vxy.md", .NO_CREATION)); | ||||
|     testing.expectError(Error.IsADirectory, openFile("/def", .NO_CREATION)); | ||||
|     testing.expectError(Error.InvalidFlags, openFile("/abc.txt", .CREATE_DIR)); | ||||
|     testing.expectError(Error.InvalidFlags, openDir("/abc.txt", .CREATE_FILE)); | ||||
|     testing.expectError(Error.NotAbsolutePath, open("", false, .NO_CREATION, .{})); | ||||
|     testing.expectError(Error.NotAbsolutePath, open("abc", false, .NO_CREATION, .{})); | ||||
|     testing.expectError(Error.NoSymlinkTarget, open("/abc", false, .CREATE_SYMLINK, .{})); | ||||
|     try testing.expectError(Error.NoSuchFileOrDir, openDir("/jkl", .NO_CREATION)); | ||||
|     try testing.expectError(Error.NoSuchFileOrDir, openFile("/mno.txt", .NO_CREATION)); | ||||
|     try testing.expectError(Error.NoSuchFileOrDir, openFile("/def/pqr.txt", .NO_CREATION)); | ||||
|     try testing.expectError(Error.NoSuchFileOrDir, openDir("/mno/stu", .NO_CREATION)); | ||||
|     try testing.expectError(Error.NoSuchFileOrDir, openFile("/mno/stu.txt", .NO_CREATION)); | ||||
|     try testing.expectError(Error.NotADirectory, openFile("/abc.txt/vxy.md", .NO_CREATION)); | ||||
|     try testing.expectError(Error.IsADirectory, openFile("/def", .NO_CREATION)); | ||||
|     try testing.expectError(Error.InvalidFlags, openFile("/abc.txt", .CREATE_DIR)); | ||||
|     try testing.expectError(Error.InvalidFlags, openDir("/abc.txt", .CREATE_FILE)); | ||||
|     try testing.expectError(Error.NotAbsolutePath, open("", false, .NO_CREATION, .{})); | ||||
|     try testing.expectError(Error.NotAbsolutePath, open("abc", false, .NO_CREATION, .{})); | ||||
|     try testing.expectError(Error.NoSymlinkTarget, open("/abc", false, .CREATE_SYMLINK, .{})); | ||||
| } | ||||
| 
 | ||||
| test "read" { | ||||
|  | @ -946,40 +948,40 @@ test "read" { | |||
|     var test_file = try openFile("/foo.txt", .CREATE_FILE); | ||||
|     var f_data = &testfs.tree.children.items[0].data; | ||||
|     var str = "test123"; | ||||
|     f_data.* = try std.mem.dupe(testing.allocator, u8, str); | ||||
|     f_data.* = try Allocator.dupe(testing.allocator, u8, str); | ||||
| 
 | ||||
|     var buffer: [64]u8 = undefined; | ||||
|     { | ||||
|         const length = try test_file.read(buffer[0..str.len]); | ||||
|         testing.expect(std.mem.eql(u8, str, buffer[0..length])); | ||||
|         try testing.expect(std.mem.eql(u8, str, buffer[0..length])); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|         const length = try test_file.read(buffer[0 .. str.len + 1]); | ||||
|         testing.expect(std.mem.eql(u8, str, buffer[0..length])); | ||||
|         try testing.expect(std.mem.eql(u8, str, buffer[0..length])); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|         const length = try test_file.read(buffer[0 .. str.len + 3]); | ||||
|         testing.expect(std.mem.eql(u8, str, buffer[0..length])); | ||||
|         try testing.expect(std.mem.eql(u8, str, buffer[0..length])); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|         const length = try test_file.read(buffer[0 .. str.len - 1]); | ||||
|         testing.expect(std.mem.eql(u8, str[0 .. str.len - 1], buffer[0..length])); | ||||
|         try testing.expect(std.mem.eql(u8, str[0 .. str.len - 1], buffer[0..length])); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|         const length = try test_file.read(buffer[0..0]); | ||||
|         testing.expect(std.mem.eql(u8, str[0..0], buffer[0..length])); | ||||
|         try testing.expect(std.mem.eql(u8, str[0..0], buffer[0..length])); | ||||
|     } | ||||
|     // Try reading from a symlink | ||||
|     var test_link = try openSymlink("/link", "/foo.txt", .CREATE_SYMLINK); | ||||
|     testing.expectEqual(test_link, "/foo.txt"); | ||||
|     try testing.expectEqual(test_link, "/foo.txt"); | ||||
|     var link_file = try openFile("/link", .NO_CREATION); | ||||
|     { | ||||
|         const length = try link_file.read(buffer[0..]); | ||||
|         testing.expect(std.mem.eql(u8, str[0..], buffer[0..length])); | ||||
|         try testing.expect(std.mem.eql(u8, str[0..], buffer[0..length])); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -991,19 +993,19 @@ test "write" { | |||
| 
 | ||||
|     var test_file = try openFile("/foo.txt", .CREATE_FILE); | ||||
|     var f_data = &testfs.tree.children.items[0].data; | ||||
|     testing.expectEqual(f_data.*, null); | ||||
|     try testing.expectEqual(f_data.*, null); | ||||
| 
 | ||||
|     var str = "test123"; | ||||
|     const length = try test_file.write(str); | ||||
|     testing.expect(std.mem.eql(u8, str, f_data.* orelse unreachable)); | ||||
|     testing.expect(length == str.len); | ||||
|     try testing.expect(std.mem.eql(u8, str, f_data.* orelse unreachable)); | ||||
|     try testing.expect(length == str.len); | ||||
| 
 | ||||
|     // Try writing to a symlink | ||||
|     var test_link = try openSymlink("/link", "/foo.txt", .CREATE_SYMLINK); | ||||
|     testing.expectEqual(test_link, "/foo.txt"); | ||||
|     var link_file = try openFile("/link", .NO_CREATION); | ||||
|     try testing.expectEqual(test_link, "/foo.txt"); | ||||
|     _ = try openFile("/link", .NO_CREATION); | ||||
| 
 | ||||
|     var str2 = "test456"; | ||||
|     const length2 = try test_file.write(str2); | ||||
|     testing.expect(std.mem.eql(u8, str2, f_data.* orelse unreachable)); | ||||
|     _ = try test_file.write(str2); | ||||
|     try testing.expect(std.mem.eql(u8, str2, f_data.* orelse unreachable)); | ||||
| } | ||||
|  |  | |||
|  | @ -2,10 +2,9 @@ const std = @import("std"); | |||
| const Allocator = std.mem.Allocator; | ||||
| const testing = std.testing; | ||||
| const log = std.log.scoped(.heap); | ||||
| const builtin = @import("builtin"); | ||||
| const builtin = std.builtin; | ||||
| const is_test = builtin.is_test; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.mock_path; | ||||
| const vmm = @import("vmm.zig"); | ||||
| const panic = @import("panic.zig").panic; | ||||
| 
 | ||||
|  | @ -15,7 +14,7 @@ pub const FreeListAllocator = struct { | |||
|         size: usize, | ||||
|         next_free: ?*Header, | ||||
| 
 | ||||
|         const Self = @Self(); | ||||
|         const Self = @This(); | ||||
| 
 | ||||
|         /// | ||||
|         /// Initialise the header for a free allocation node | ||||
|  | @ -33,9 +32,9 @@ pub const FreeListAllocator = struct { | |||
|             }; | ||||
|         } | ||||
|     }; | ||||
|     const Self = @This(); | ||||
| 
 | ||||
|     first_free: ?*Header, | ||||
|     allocator: Allocator, | ||||
| 
 | ||||
|     /// | ||||
|     /// Initialise an empty and free FreeListAllocator | ||||
|  | @ -54,13 +53,13 @@ pub const FreeListAllocator = struct { | |||
|         if (size <= @sizeOf(Header)) return Error.TooSmall; | ||||
|         return FreeListAllocator{ | ||||
|             .first_free = insertFreeHeader(start, size - @sizeOf(Header), null), | ||||
|             .allocator = .{ | ||||
|                 .allocFn = alloc, | ||||
|                 .resizeFn = resize, | ||||
|             }, | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     pub fn allocator(self: *Self) Allocator { | ||||
|         return Allocator.init(self, alloc, resize, free); | ||||
|     } | ||||
| 
 | ||||
|     /// | ||||
|     /// Create a free header at a specific location | ||||
|     /// | ||||
|  | @ -86,7 +85,7 @@ pub const FreeListAllocator = struct { | |||
|     ///     IN previous: ?*Header - The previous free node or null if there wasn't one. If null, self.first_free will be set to header, else previous.next_free will be set to header | ||||
|     ///     IN header: ?*Header - The header being pointed to. This will be the new value of self.first_free or previous.next_free | ||||
|     /// | ||||
|     fn registerFreeHeader(self: *FreeListAllocator, previous: ?*Header, header: ?*Header) void { | ||||
|     fn registerFreeHeader(self: *Self, previous: ?*Header, header: ?*Header) void { | ||||
|         if (previous) |p| { | ||||
|             p.next_free = header; | ||||
|         } else { | ||||
|  | @ -100,8 +99,12 @@ pub const FreeListAllocator = struct { | |||
|     /// Arguments: | ||||
|     ///     IN self: *FreeListAllocator - The allocator being freed within | ||||
|     ///     IN mem: []u8 - The memory to free | ||||
|     ///     IN alignment: u29 - The alignment used to allocate the memory | ||||
|     ///     IN ret_addr: usize - The return address passed by the high-level Allocator API. This is ignored. | ||||
|     /// | ||||
|     fn free(self: *FreeListAllocator, mem: []u8) void { | ||||
|     fn free(self: *Self, mem: []u8, alignment: u29, ret_addr: usize) void { | ||||
|         _ = alignment; | ||||
|         _ = ret_addr; | ||||
|         const size = std.math.max(mem.len, @sizeOf(Header)); | ||||
|         const addr = @ptrToInt(mem.ptr); | ||||
|         var header = insertFreeHeader(addr, size - @sizeOf(Header), null); | ||||
|  | @ -181,23 +184,22 @@ pub const FreeListAllocator = struct { | |||
|     /// The node before old_mem needs to then point to the new header and the new header needs to point to the next free node. | ||||
|     /// | ||||
|     /// Arguments: | ||||
|     ///     IN allocator: *std.Allocator - The allocator to resize within. | ||||
|     ///     IN self: *FreeListAllocator - The allocator to resize within. | ||||
|     ///     IN old_mem: []u8 - The buffer to resize. | ||||
|     ///     IN old_align: u29 - The original alignment for old_mem. | ||||
|     ///     IN new_size: usize - What to resize to. | ||||
|     ///     IN size_alignment: u29 - The alignment that the size should have. | ||||
|     ///     IN ret_addr: usize - The return address passed by the high-level Allocator API. This is ignored | ||||
|     /// | ||||
|     /// Return: usize | ||||
|     ///     The new size of the buffer, which will be new_size if the operation was successful. | ||||
|     /// Return: ?usize | ||||
|     ///     The new size of the buffer, which will be new_size if the operation was successfull, or null if the operation wasn't successful. | ||||
|     /// | ||||
|     /// Error: std.Allocator.Error | ||||
|     ///     std.Allocator.Error.OutOfMemory - If there wasn't enough free memory to expand into | ||||
|     /// | ||||
|     fn resize(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, size_alignment: u29, ret_addr: usize) Allocator.Error!usize { | ||||
|         var self = @fieldParentPtr(FreeListAllocator, "allocator", allocator); | ||||
|     fn resize(self: *Self, old_mem: []u8, old_align: u29, new_size: usize, size_alignment: u29, ret_addr: usize) ?usize { | ||||
|         // Suppress unused var warning | ||||
|         _ = old_align; | ||||
|         _ = ret_addr; | ||||
|         if (new_size == 0) { | ||||
|             self.free(old_mem); | ||||
|             self.free(old_mem, old_align, ret_addr); | ||||
|             return 0; | ||||
|         } | ||||
|         if (new_size == old_mem.len) return new_size; | ||||
|  | @ -227,12 +229,12 @@ pub const FreeListAllocator = struct { | |||
|         if (real_size > old_mem.len) { | ||||
|             if (next) |n| { | ||||
|                 // If the free neighbour isn't big enough then fail | ||||
|                 if (old_mem.len + n.size + @sizeOf(Header) < real_size) return Allocator.Error.OutOfMemory; | ||||
|                 if (old_mem.len + n.size + @sizeOf(Header) < real_size) return null; | ||||
| 
 | ||||
|                 const size_diff = real_size - old_mem.len; | ||||
|                 const consumes_whole_neighbour = size_diff == n.size + @sizeOf(Header); | ||||
|                 // If the space left over in the free neighbour from the resize isn't enough to fit a new node, then fail | ||||
|                 if (!consumes_whole_neighbour and n.size + @sizeOf(Header) - size_diff < @sizeOf(Header)) return Allocator.Error.OutOfMemory; | ||||
|                 if (!consumes_whole_neighbour and n.size + @sizeOf(Header) - size_diff < @sizeOf(Header)) return null; | ||||
|                 var new_next: ?*Header = n.next_free; | ||||
|                 // We don't do any splitting when consuming the whole neighbour | ||||
|                 if (!consumes_whole_neighbour) { | ||||
|  | @ -244,7 +246,7 @@ pub const FreeListAllocator = struct { | |||
|                 return real_size; | ||||
|             } | ||||
|             // The neighbour isn't free so we can't expand into it | ||||
|             return Allocator.Error.OutOfMemory; | ||||
|             return null; | ||||
|         } else { | ||||
|             // Shrinking | ||||
|             var size_diff = old_mem.len - real_size; | ||||
|  | @ -303,7 +305,7 @@ pub const FreeListAllocator = struct { | |||
|     /// Splitting on the left and right can both happen in one allocation | ||||
|     /// | ||||
|     /// Arguments: | ||||
|     ///     IN allocator: *std.Allocator - The allocator to use | ||||
|     ///     IN self: *FreeListAllocator - The allocator to use | ||||
|     ///     IN size: usize - The amount of memory requested | ||||
|     ///     IN alignment: u29 - The alignment that the address of the allocated memory should have | ||||
|     ///     IN size_alignment: u29 - The alignment that the length of the allocated memory should have | ||||
|  | @ -315,8 +317,9 @@ pub const FreeListAllocator = struct { | |||
|     /// Error: std.Allocator.Error | ||||
|     ///     std.Allocator.Error.OutOfMemory - There wasn't enough memory left to fulfill the request | ||||
|     /// | ||||
|     pub fn alloc(allocator: *Allocator, size: usize, alignment: u29, size_alignment: u29, ret_addr: usize) Allocator.Error![]u8 { | ||||
|         var self = @fieldParentPtr(FreeListAllocator, "allocator", allocator); | ||||
|     pub fn alloc(self: *Self, size: usize, alignment: u29, size_alignment: u29, ret_addr: usize) Allocator.Error![]u8 { | ||||
|         // Suppress unused var warning | ||||
|         _ = ret_addr; | ||||
|         if (self.first_free == null) return Allocator.Error.OutOfMemory; | ||||
| 
 | ||||
|         // Get the real size being allocated, which is the aligned size or the size of a header (whichever is largest) | ||||
|  | @ -420,11 +423,11 @@ pub const FreeListAllocator = struct { | |||
|         var free_list = &(try FreeListAllocator.init(@ptrToInt(region.ptr), size)); | ||||
| 
 | ||||
|         var header = @intToPtr(*FreeListAllocator.Header, @ptrToInt(region.ptr)); | ||||
|         testing.expectEqual(header, free_list.first_free.?); | ||||
|         testing.expectEqual(header.next_free, null); | ||||
|         testing.expectEqual(header.size, size - @sizeOf(Header)); | ||||
|         try testing.expectEqual(header, free_list.first_free.?); | ||||
|         try testing.expectEqual(header.next_free, null); | ||||
|         try testing.expectEqual(header.size, size - @sizeOf(Header)); | ||||
| 
 | ||||
|         testing.expectError(Error.TooSmall, FreeListAllocator.init(0, @sizeOf(Header) - 1)); | ||||
|         try testing.expectError(Error.TooSmall, FreeListAllocator.init(0, @sizeOf(Header) - 1)); | ||||
|     } | ||||
| 
 | ||||
|     test "alloc" { | ||||
|  | @ -433,79 +436,77 @@ pub const FreeListAllocator = struct { | |||
|         defer testing.allocator.free(region); | ||||
|         const start = @ptrToInt(region.ptr); | ||||
|         var free_list = &(try FreeListAllocator.init(start, size)); | ||||
|         var allocator = &free_list.allocator; | ||||
| 
 | ||||
|         std.debug.warn("", .{}); | ||||
|         std.debug.print("", .{}); | ||||
| 
 | ||||
|         const alloc0 = try alloc(allocator, 64, 0, 0, @returnAddress()); | ||||
|         const alloc0 = try free_list.alloc(64, 0, 0, @returnAddress()); | ||||
|         const alloc0_addr = @ptrToInt(alloc0.ptr); | ||||
|         // Should be at the start of the heap | ||||
|         testing.expectEqual(alloc0_addr, start); | ||||
|         try testing.expectEqual(alloc0_addr, start); | ||||
|         // The allocation should have produced a node on the right of the allocation | ||||
|         var header = @intToPtr(*Header, start + 64); | ||||
|         testing.expectEqual(header.size, size - 64 - @sizeOf(Header)); | ||||
|         testing.expectEqual(header.next_free, null); | ||||
|         testing.expectEqual(free_list.first_free, header); | ||||
|         try testing.expectEqual(header.size, size - 64 - @sizeOf(Header)); | ||||
|         try testing.expectEqual(header.next_free, null); | ||||
|         try testing.expectEqual(free_list.first_free, header); | ||||
| 
 | ||||
|         std.debug.warn("", .{}); | ||||
|         std.debug.print("", .{}); | ||||
| 
 | ||||
|         // 64 bytes aligned to 4 bytes | ||||
|         const alloc1 = try alloc(allocator, 64, 4, 0, @returnAddress()); | ||||
|         const alloc1 = try free_list.alloc(64, 4, 0, @returnAddress()); | ||||
|         const alloc1_addr = @ptrToInt(alloc1.ptr); | ||||
|         const alloc1_end = alloc1_addr + alloc1.len; | ||||
|         // Should be to the right of the first allocation, with some alignment padding in between | ||||
|         const alloc0_end = alloc0_addr + alloc0.len; | ||||
|         testing.expect(alloc0_end <= alloc1_addr); | ||||
|         testing.expectEqual(std.mem.alignForward(alloc0_end, 4), alloc1_addr); | ||||
|         try testing.expect(alloc0_end <= alloc1_addr); | ||||
|         try testing.expectEqual(std.mem.alignForward(alloc0_end, 4), alloc1_addr); | ||||
|         // It should have produced a node on the right | ||||
|         header = @intToPtr(*Header, alloc1_end); | ||||
|         testing.expectEqual(header.size, size - (alloc1_end - start) - @sizeOf(Header)); | ||||
|         testing.expectEqual(header.next_free, null); | ||||
|         testing.expectEqual(free_list.first_free, header); | ||||
|         try testing.expectEqual(header.size, size - (alloc1_end - start) - @sizeOf(Header)); | ||||
|         try testing.expectEqual(header.next_free, null); | ||||
|         try testing.expectEqual(free_list.first_free, header); | ||||
| 
 | ||||
|         const alloc2 = try alloc(allocator, 64, 256, 0, @returnAddress()); | ||||
|         const alloc2 = try free_list.alloc(64, 256, 0, @returnAddress()); | ||||
|         const alloc2_addr = @ptrToInt(alloc2.ptr); | ||||
|         const alloc2_end = alloc2_addr + alloc2.len; | ||||
|         testing.expect(alloc1_end < alloc2_addr); | ||||
|         try testing.expect(alloc1_end < alloc2_addr); | ||||
|         // There should be a free node to the right of alloc2 | ||||
|         const second_header = @intToPtr(*Header, alloc2_end); | ||||
|         testing.expectEqual(second_header.size, size - (alloc2_end - start) - @sizeOf(Header)); | ||||
|         testing.expectEqual(second_header.next_free, null); | ||||
|         try testing.expectEqual(second_header.size, size - (alloc2_end - start) - @sizeOf(Header)); | ||||
|         try testing.expectEqual(second_header.next_free, null); | ||||
|         // There should be a free node in between alloc1 and alloc2 due to the large alignment padding (depends on the allocation by the testing allocator, hence the check) | ||||
|         if (alloc2_addr - alloc1_end >= @sizeOf(Header)) { | ||||
|             header = @intToPtr(*Header, alloc1_end); | ||||
|             testing.expectEqual(free_list.first_free, header); | ||||
|             testing.expectEqual(header.next_free, second_header); | ||||
|             try testing.expectEqual(free_list.first_free, header); | ||||
|             try testing.expectEqual(header.next_free, second_header); | ||||
|         } | ||||
| 
 | ||||
|         // Try allocating something smaller than @sizeOf(Header). This should scale up to @sizeOf(Header) | ||||
|         var alloc3 = try alloc(allocator, 1, 0, 0, @returnAddress()); | ||||
|         var alloc3 = try free_list.alloc(1, 0, 0, @returnAddress()); | ||||
|         const alloc3_addr = @ptrToInt(alloc3.ptr); | ||||
|         const alloc3_end = alloc3_addr + @sizeOf(Header); | ||||
|         const header2 = @intToPtr(*Header, alloc3_end); | ||||
|         // The new free node on the right should be the first one free | ||||
|         testing.expectEqual(free_list.first_free, header2); | ||||
|         try testing.expectEqual(free_list.first_free, header2); | ||||
|         // And it should point to the free node on the right of alloc2 | ||||
|         testing.expectEqual(header2.next_free, second_header); | ||||
|         try testing.expectEqual(header2.next_free, second_header); | ||||
| 
 | ||||
|         // Attempting to allocate more than the size of the largest free node should fail | ||||
|         const remaining_size = second_header.size + @sizeOf(Header); | ||||
|         testing.expectError(Allocator.Error.OutOfMemory, alloc(&free_list.allocator, remaining_size + 1, 0, 0, @returnAddress())); | ||||
|         try testing.expectError(Allocator.Error.OutOfMemory, free_list.alloc(remaining_size + 1, 0, 0, @returnAddress())); | ||||
| 
 | ||||
|         // Alloc a non aligned to header | ||||
|         var alloc4 = try alloc(allocator, 13, 1, 0, @returnAddress()); | ||||
|         var alloc4 = try free_list.alloc(13, 1, 0, @returnAddress()); | ||||
|         const alloc4_addr = @ptrToInt(alloc4.ptr); | ||||
|         const alloc4_end = alloc4_addr + std.mem.alignForward(13, @alignOf(Header)); | ||||
|         const header3 = @intToPtr(*Header, alloc4_end); | ||||
|         const header4 = @intToPtr(*Header, alloc4_addr); | ||||
| 
 | ||||
|         // We should still have a length of 13 | ||||
|         testing.expectEqual(alloc4.len, 13); | ||||
|         try testing.expectEqual(alloc4.len, 13); | ||||
|         // But this should be aligned to Header (4) | ||||
|         testing.expectEqual(alloc4_end - alloc4_addr, 16); | ||||
|         try testing.expectEqual(alloc4_end - alloc4_addr, 16); | ||||
| 
 | ||||
|         // Previous header should now point to the next header | ||||
|         testing.expectEqual(header2.next_free, header3); | ||||
|         try testing.expectEqual(header2.next_free, header3); | ||||
|     } | ||||
| 
 | ||||
|     test "free" { | ||||
|  | @ -514,74 +515,72 @@ pub const FreeListAllocator = struct { | |||
|         defer testing.allocator.free(region); | ||||
|         const start = @ptrToInt(region.ptr); | ||||
|         var free_list = &(try FreeListAllocator.init(start, size)); | ||||
|         var allocator = &free_list.allocator; | ||||
| 
 | ||||
|         var alloc0 = try alloc(allocator, 128, 0, 0, @returnAddress()); | ||||
|         var alloc1 = try alloc(allocator, 256, 0, 0, @returnAddress()); | ||||
|         var alloc2 = try alloc(allocator, 64, 0, 0, @returnAddress()); | ||||
|         var alloc0 = try free_list.alloc(128, 0, 0, @returnAddress()); | ||||
|         var alloc1 = try free_list.alloc(256, 0, 0, @returnAddress()); | ||||
|         var alloc2 = try free_list.alloc(64, 0, 0, @returnAddress()); | ||||
| 
 | ||||
|         // There should be a single free node after alloc2 | ||||
|         const free_node3 = @intToPtr(*Header, @ptrToInt(alloc2.ptr) + alloc2.len); | ||||
|         testing.expectEqual(free_list.first_free, free_node3); | ||||
|         testing.expectEqual(free_node3.size, size - alloc0.len - alloc1.len - alloc2.len - @sizeOf(Header)); | ||||
|         testing.expectEqual(free_node3.next_free, null); | ||||
|         try testing.expectEqual(free_list.first_free, free_node3); | ||||
|         try testing.expectEqual(free_node3.size, size - alloc0.len - alloc1.len - alloc2.len - @sizeOf(Header)); | ||||
|         try testing.expectEqual(free_node3.next_free, null); | ||||
| 
 | ||||
|         free_list.free(alloc0); | ||||
|         free_list.free(alloc0, 0, 0); | ||||
|         // There should now be two free nodes. One where alloc0 was and another after alloc2 | ||||
|         const free_node0 = @intToPtr(*Header, start); | ||||
|         testing.expectEqual(free_list.first_free, free_node0); | ||||
|         testing.expectEqual(free_node0.size, alloc0.len - @sizeOf(Header)); | ||||
|         testing.expectEqual(free_node0.next_free, free_node3); | ||||
|         try testing.expectEqual(free_list.first_free, free_node0); | ||||
|         try testing.expectEqual(free_node0.size, alloc0.len - @sizeOf(Header)); | ||||
|         try testing.expectEqual(free_node0.next_free, free_node3); | ||||
| 
 | ||||
|         // Freeing alloc1 should join it with free_node0 | ||||
|         free_list.free(alloc1); | ||||
|         testing.expectEqual(free_list.first_free, free_node0); | ||||
|         testing.expectEqual(free_node0.size, alloc0.len - @sizeOf(Header) + alloc1.len); | ||||
|         testing.expectEqual(free_node0.next_free, free_node3); | ||||
|         free_list.free(alloc1, 0, 0); | ||||
|         try testing.expectEqual(free_list.first_free, free_node0); | ||||
|         try testing.expectEqual(free_node0.size, alloc0.len - @sizeOf(Header) + alloc1.len); | ||||
|         try testing.expectEqual(free_node0.next_free, free_node3); | ||||
| 
 | ||||
|         // Freeing alloc2 should then join them all together into one big free node | ||||
|         free_list.free(alloc2); | ||||
|         testing.expectEqual(free_list.first_free, free_node0); | ||||
|         testing.expectEqual(free_node0.size, size - @sizeOf(Header)); | ||||
|         testing.expectEqual(free_node0.next_free, null); | ||||
|         free_list.free(alloc2, 0, 0); | ||||
|         try testing.expectEqual(free_list.first_free, free_node0); | ||||
|         try testing.expectEqual(free_node0.size, size - @sizeOf(Header)); | ||||
|         try testing.expectEqual(free_node0.next_free, null); | ||||
|     } | ||||
| 
 | ||||
|     test "resize" { | ||||
|         std.debug.warn("", .{}); | ||||
|         std.debug.print("", .{}); | ||||
|         const size = 1024; | ||||
|         var region = try testing.allocator.alloc(u8, size); | ||||
|         defer testing.allocator.free(region); | ||||
|         const start = @ptrToInt(region.ptr); | ||||
|         var free_list = &(try FreeListAllocator.init(start, size)); | ||||
|         var allocator = &free_list.allocator; | ||||
| 
 | ||||
|         var alloc0 = try alloc(allocator, 128, 0, 0, @returnAddress()); | ||||
|         var alloc1 = try alloc(allocator, 256, 0, 0, @returnAddress()); | ||||
|         var alloc0 = try free_list.alloc(128, 0, 0, @returnAddress()); | ||||
|         var alloc1 = try free_list.alloc(256, 0, 0, @returnAddress()); | ||||
| 
 | ||||
|         // Expanding alloc0 should fail as alloc1 is right next to it | ||||
|         testing.expectError(Allocator.Error.OutOfMemory, resize(&free_list.allocator, alloc0, 0, 136, 0, @returnAddress())); | ||||
|         try testing.expectEqual(free_list.resize(alloc0, 0, 136, 0, @returnAddress()), null); | ||||
| 
 | ||||
|         // Expanding alloc1 should succeed | ||||
|         testing.expectEqual(try resize(allocator, alloc1, 0, 512, 0, @returnAddress()), 512); | ||||
|         try testing.expectEqual(free_list.resize(alloc1, 0, 512, 0, @returnAddress()), 512); | ||||
|         alloc1 = alloc1.ptr[0..512]; | ||||
|         // And there should be a free node on the right of it | ||||
|         var header = @intToPtr(*Header, @ptrToInt(alloc1.ptr) + 512); | ||||
|         testing.expectEqual(header.size, size - 128 - 512 - @sizeOf(Header)); | ||||
|         testing.expectEqual(header.next_free, null); | ||||
|         testing.expectEqual(free_list.first_free, header); | ||||
|         try testing.expectEqual(header.size, size - 128 - 512 - @sizeOf(Header)); | ||||
|         try testing.expectEqual(header.next_free, null); | ||||
|         try testing.expectEqual(free_list.first_free, header); | ||||
| 
 | ||||
|         // Shrinking alloc1 should produce a big free node on the right | ||||
|         testing.expectEqual(try resize(allocator, alloc1, 0, 128, 0, @returnAddress()), 128); | ||||
|         try testing.expectEqual(free_list.resize(alloc1, 0, 128, 0, @returnAddress()), 128); | ||||
|         alloc1 = alloc1.ptr[0..128]; | ||||
|         header = @intToPtr(*Header, @ptrToInt(alloc1.ptr) + 128); | ||||
|         testing.expectEqual(header.size, size - 128 - 128 - @sizeOf(Header)); | ||||
|         testing.expectEqual(header.next_free, null); | ||||
|         testing.expectEqual(free_list.first_free, header); | ||||
|         try testing.expectEqual(header.size, size - 128 - 128 - @sizeOf(Header)); | ||||
|         try testing.expectEqual(header.next_free, null); | ||||
|         try testing.expectEqual(free_list.first_free, header); | ||||
| 
 | ||||
|         // Shrinking by less space than would allow for a new Header shouldn't work | ||||
|         testing.expectEqual(resize(allocator, alloc1, 0, alloc1.len - @sizeOf(Header) / 2, 0, @returnAddress()), 128); | ||||
|         try testing.expectEqual(free_list.resize(alloc1, 0, alloc1.len - @sizeOf(Header) / 2, 0, @returnAddress()), 128); | ||||
|         // Shrinking to less space than would allow for a new Header shouldn't work | ||||
|         testing.expectEqual(resize(allocator, alloc1, 0, @sizeOf(Header) / 2, 0, @returnAddress()), @sizeOf(Header)); | ||||
|         try testing.expectEqual(free_list.resize(alloc1, 0, @sizeOf(Header) / 2, 0, @returnAddress()), @sizeOf(Header)); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -216,44 +216,44 @@ pub const Keyboard = struct { | |||
| 
 | ||||
|     test "init" { | ||||
|         const keyboard = Keyboard.init(); | ||||
|         testing.expectEqual(keyboard.queue_front, 0); | ||||
|         testing.expectEqual(keyboard.queue_end, 0); | ||||
|         try testing.expectEqual(keyboard.queue_front, 0); | ||||
|         try testing.expectEqual(keyboard.queue_end, 0); | ||||
|     } | ||||
| 
 | ||||
|     test "isEmpty" { | ||||
|         var keyboard = Keyboard.init(); | ||||
|         testing.expect(keyboard.isEmpty()); | ||||
|         try testing.expect(keyboard.isEmpty()); | ||||
| 
 | ||||
|         keyboard.queue_end += 1; | ||||
|         testing.expect(!keyboard.isEmpty()); | ||||
|         try testing.expect(!keyboard.isEmpty()); | ||||
| 
 | ||||
|         keyboard.queue_front += 1; | ||||
|         testing.expect(keyboard.isEmpty()); | ||||
|         try testing.expect(keyboard.isEmpty()); | ||||
| 
 | ||||
|         keyboard.queue_end = std.math.maxInt(QueueIndex); | ||||
|         keyboard.queue_front = 0; | ||||
|         testing.expect(!keyboard.isEmpty()); | ||||
|         try testing.expect(!keyboard.isEmpty()); | ||||
| 
 | ||||
|         keyboard.queue_front = std.math.maxInt(QueueIndex); | ||||
|         testing.expect(keyboard.isEmpty()); | ||||
|         try testing.expect(keyboard.isEmpty()); | ||||
|     } | ||||
| 
 | ||||
|     test "isFull" { | ||||
|         var keyboard = Keyboard.init(); | ||||
|         testing.expect(!keyboard.isFull()); | ||||
|         try testing.expect(!keyboard.isFull()); | ||||
| 
 | ||||
|         keyboard.queue_end += 1; | ||||
|         testing.expect(!keyboard.isFull()); | ||||
|         try testing.expect(!keyboard.isFull()); | ||||
| 
 | ||||
|         keyboard.queue_front += 1; | ||||
|         testing.expect(!keyboard.isFull()); | ||||
|         try testing.expect(!keyboard.isFull()); | ||||
| 
 | ||||
|         keyboard.queue_end = 0; | ||||
|         testing.expect(keyboard.isFull()); | ||||
|         try testing.expect(keyboard.isFull()); | ||||
| 
 | ||||
|         keyboard.queue_front = 0; | ||||
|         keyboard.queue_end = std.math.maxInt(QueueIndex); | ||||
|         testing.expect(keyboard.isFull()); | ||||
|         try testing.expect(keyboard.isFull()); | ||||
|     } | ||||
| 
 | ||||
|     test "writeKey" { | ||||
|  | @ -261,20 +261,20 @@ pub const Keyboard = struct { | |||
| 
 | ||||
|         comptime var i = 0; | ||||
|         inline while (i < QUEUE_SIZE - 1) : (i += 1) { | ||||
|             testing.expectEqual(keyboard.writeKey(.{ | ||||
|             try testing.expectEqual(keyboard.writeKey(.{ | ||||
|                 .position = @intToEnum(KeyPosition, i), | ||||
|                 .released = false, | ||||
|             }), true); | ||||
|             testing.expectEqual(keyboard.queue[i].position, @intToEnum(KeyPosition, i)); | ||||
|             testing.expectEqual(keyboard.queue_end, i + 1); | ||||
|             testing.expectEqual(keyboard.queue_front, 0); | ||||
|             try testing.expectEqual(keyboard.queue[i].position, @intToEnum(KeyPosition, i)); | ||||
|             try testing.expectEqual(keyboard.queue_end, i + 1); | ||||
|             try testing.expectEqual(keyboard.queue_front, 0); | ||||
|         } | ||||
| 
 | ||||
|         testing.expectEqual(keyboard.writeKey(.{ | ||||
|         try testing.expectEqual(keyboard.writeKey(.{ | ||||
|             .position = @intToEnum(KeyPosition, 33), | ||||
|             .released = false, | ||||
|         }), false); | ||||
|         testing.expect(keyboard.isFull()); | ||||
|         try testing.expect(keyboard.isFull()); | ||||
|     } | ||||
| 
 | ||||
|     test "readKey" { | ||||
|  | @ -282,7 +282,7 @@ pub const Keyboard = struct { | |||
| 
 | ||||
|         comptime var i = 0; | ||||
|         inline while (i < QUEUE_SIZE - 1) : (i += 1) { | ||||
|             testing.expectEqual(keyboard.writeKey(.{ | ||||
|             try testing.expectEqual(keyboard.writeKey(.{ | ||||
|                 .position = @intToEnum(KeyPosition, i), | ||||
|                 .released = false, | ||||
|             }), true); | ||||
|  | @ -290,13 +290,13 @@ pub const Keyboard = struct { | |||
| 
 | ||||
|         i = 0; | ||||
|         inline while (i < QUEUE_SIZE - 1) : (i += 1) { | ||||
|             testing.expectEqual(keyboard.readKey().?.position, @intToEnum(KeyPosition, i)); | ||||
|             testing.expectEqual(keyboard.queue_end, QUEUE_SIZE - 1); | ||||
|             testing.expectEqual(keyboard.queue_front, i + 1); | ||||
|             try testing.expectEqual(keyboard.readKey().?.position, @intToEnum(KeyPosition, i)); | ||||
|             try testing.expectEqual(keyboard.queue_end, QUEUE_SIZE - 1); | ||||
|             try testing.expectEqual(keyboard.queue_front, i + 1); | ||||
|         } | ||||
| 
 | ||||
|         testing.expect(keyboard.isEmpty()); | ||||
|         testing.expectEqual(keyboard.readKey(), null); | ||||
|         try testing.expect(keyboard.isEmpty()); | ||||
|         try testing.expectEqual(keyboard.readKey(), null); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  | @ -336,7 +336,7 @@ pub fn addKeyboard(kb: *Keyboard) Allocator.Error!void { | |||
| /// Initialise the keyboard system and the architecture's keyboard | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     allocator: *std.mem.Allocator - The allocator to initialise the keyboard list and architecture keyboard with | ||||
| ///     allocator: std.mem.Allocator - The allocator to initialise the keyboard list and architecture keyboard with | ||||
| /// | ||||
| /// Return: ?*Keyboard | ||||
| ///     The architecture keyboard found, else null if one wasn't detected | ||||
|  | @ -344,7 +344,7 @@ pub fn addKeyboard(kb: *Keyboard) Allocator.Error!void { | |||
| /// Error: std.mem.Allocator.Error | ||||
| ///     OutOfMemory - There wasn't enough memory to initialise the keyboard list or the architecture keyboard | ||||
| /// | ||||
| pub fn init(allocator: *Allocator) Allocator.Error!?*Keyboard { | ||||
| pub fn init(allocator: Allocator) Allocator.Error!?*Keyboard { | ||||
|     keyboards = ArrayList(*Keyboard).init(allocator); | ||||
|     return arch.initKeyboard(allocator); | ||||
| } | ||||
|  |  | |||
|  | @ -3,10 +3,8 @@ const kmain_log = std.log.scoped(.kmain); | |||
| const builtin = @import("builtin"); | ||||
| const is_test = builtin.is_test; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.mock_path; | ||||
| const arch = @import("arch.zig").internals; | ||||
| const tty = @import("tty.zig"); | ||||
| const vga = @import("vga.zig"); | ||||
| const log_root = @import("log.zig"); | ||||
| const pmm = @import("pmm.zig"); | ||||
| const serial = @import("serial.zig"); | ||||
|  | @ -23,7 +21,7 @@ const Allocator = std.mem.Allocator; | |||
| 
 | ||||
| comptime { | ||||
|     if (!is_test) { | ||||
|         switch (builtin.arch) { | ||||
|         switch (builtin.cpu.arch) { | ||||
|             .i386 => _ = @import("arch/x86/boot.zig"), | ||||
|             else => unreachable, | ||||
|         } | ||||
|  | @ -42,7 +40,7 @@ export var KERNEL_PHYSADDR_START: u32 = if (builtin.is_test) 0x100000 else undef | |||
| export var KERNEL_PHYSADDR_END: u32 = if (builtin.is_test) 0x14E000 else undefined; | ||||
| 
 | ||||
| // Just call the panic function, as this need to be in the root source file | ||||
| pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn { | ||||
| pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { | ||||
|     @setCold(true); | ||||
|     panic_root.panic(error_return_trace, "{s}", .{msg}); | ||||
| } | ||||
|  | @ -62,7 +60,6 @@ var kernel_heap: heap.FreeListAllocator = undefined; | |||
| 
 | ||||
| export fn kmain(boot_payload: arch.BootPayload) void { | ||||
|     const serial_stream = serial.init(boot_payload); | ||||
| 
 | ||||
|     log_root.init(serial_stream); | ||||
| 
 | ||||
|     const mem_profile = arch.initMem(boot_payload) catch |e| { | ||||
|  | @ -70,19 +67,19 @@ export fn kmain(boot_payload: arch.BootPayload) void { | |||
|     }; | ||||
|     var fixed_allocator = mem_profile.fixed_allocator; | ||||
| 
 | ||||
|     panic_root.init(&mem_profile, &fixed_allocator.allocator) catch |e| { | ||||
|         panic_root.panic(@errorReturnTrace(), "Failed to initialise panic: {}\n", .{e}); | ||||
|     }; | ||||
| 
 | ||||
|     pmm.init(&mem_profile, &fixed_allocator.allocator); | ||||
|     var kernel_vmm = vmm.init(&mem_profile, &fixed_allocator.allocator) catch |e| { | ||||
|     pmm.init(&mem_profile, fixed_allocator.allocator()); | ||||
|     var kernel_vmm = vmm.init(&mem_profile, fixed_allocator.allocator()) catch |e| { | ||||
|         panic_root.panic(@errorReturnTrace(), "Failed to initialise kernel VMM: {}", .{e}); | ||||
|     }; | ||||
| 
 | ||||
|     kmain_log.info("Init arch " ++ @tagName(builtin.arch) ++ "\n", .{}); | ||||
|     kmain_log.info("Init arch " ++ @tagName(builtin.cpu.arch) ++ "\n", .{}); | ||||
|     arch.init(&mem_profile); | ||||
|     kmain_log.info("Arch init done\n", .{}); | ||||
| 
 | ||||
|     panic_root.initSymbols(&mem_profile, fixed_allocator.allocator()) catch |e| { | ||||
|         panic_root.panic(@errorReturnTrace(), "Failed to initialise panic symbols: {}\n", .{e}); | ||||
|     }; | ||||
| 
 | ||||
|     // The VMM runtime tests can't happen until the architecture has initialised itself | ||||
|     switch (build_options.test_mode) { | ||||
|         .Initialisation => vmm.runtimeTests(arch.VmmPayload, kernel_vmm, &mem_profile), | ||||
|  | @ -99,8 +96,8 @@ export fn kmain(boot_payload: arch.BootPayload) void { | |||
|         panic_root.panic(@errorReturnTrace(), "Failed to initialise kernel heap: {}\n", .{e}); | ||||
|     }; | ||||
| 
 | ||||
|     tty.init(&kernel_heap.allocator, boot_payload); | ||||
|     var arch_kb = keyboard.init(&fixed_allocator.allocator) catch |e| { | ||||
|     tty.init(kernel_heap.allocator(), boot_payload); | ||||
|     var arch_kb = keyboard.init(fixed_allocator.allocator()) catch |e| { | ||||
|         panic_root.panic(@errorReturnTrace(), "Failed to inititalise keyboard: {}\n", .{e}); | ||||
|     }; | ||||
|     if (arch_kb) |kb| { | ||||
|  | @ -119,7 +116,7 @@ export fn kmain(boot_payload: arch.BootPayload) void { | |||
|         const rd_len: usize = module.region.end - module.region.start; | ||||
|         const ramdisk_bytes = @intToPtr([*]u8, module.region.start)[0..rd_len]; | ||||
|         var initrd_stream = std.io.fixedBufferStream(ramdisk_bytes); | ||||
|         var ramdisk_filesystem = initrd.InitrdFS.init(&initrd_stream, &kernel_heap.allocator) catch |e| { | ||||
|         var ramdisk_filesystem = initrd.InitrdFS.init(&initrd_stream, kernel_heap.allocator()) catch |e| { | ||||
|             panic_root.panic(@errorReturnTrace(), "Failed to initialise ramdisk: {}\n", .{e}); | ||||
|         }; | ||||
| 
 | ||||
|  | @ -134,7 +131,7 @@ export fn kmain(boot_payload: arch.BootPayload) void { | |||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     scheduler.init(&kernel_heap.allocator, &mem_profile) catch |e| { | ||||
|     scheduler.init(kernel_heap.allocator(), &mem_profile) catch |e| { | ||||
|         panic_root.panic(@errorReturnTrace(), "Failed to initialise scheduler: {}\n", .{e}); | ||||
|     }; | ||||
| 
 | ||||
|  | @ -147,10 +144,10 @@ export fn kmain(boot_payload: arch.BootPayload) void { | |||
|     kmain_log.info("Creating init2\n", .{}); | ||||
| 
 | ||||
|     // Create a init2 task | ||||
|     var stage2_task = task.Task.create(@ptrToInt(initStage2), true, kernel_vmm, &kernel_heap.allocator) catch |e| { | ||||
|     var stage2_task = task.Task.create(@ptrToInt(initStage2), true, kernel_vmm, kernel_heap.allocator()) catch |e| { | ||||
|         panic_root.panic(@errorReturnTrace(), "Failed to create init stage 2 task: {}\n", .{e}); | ||||
|     }; | ||||
|     scheduler.scheduleTask(stage2_task, &kernel_heap.allocator) catch |e| { | ||||
|     scheduler.scheduleTask(stage2_task, kernel_heap.allocator()) catch |e| { | ||||
|         panic_root.panic(@errorReturnTrace(), "Failed to schedule init stage 2 task: {}\n", .{e}); | ||||
|     }; | ||||
| 
 | ||||
|  | @ -177,7 +174,7 @@ fn initStage2() noreturn { | |||
| 
 | ||||
|     tty.print("Hello Pluto from kernel :)\n", .{}); | ||||
| 
 | ||||
|     const devices = arch.getDevices(&kernel_heap.allocator) catch |e| { | ||||
|     const devices = arch.getDevices(kernel_heap.allocator()) catch |e| { | ||||
|         panic_root.panic(@errorReturnTrace(), "Unable to get device list: {}\n", .{e}); | ||||
|     }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,6 +28,8 @@ var serial: Serial = undefined; | |||
| ///     {} - No error as LoggingError is empty. | ||||
| /// | ||||
| fn logCallback(context: void, str: []const u8) LoggingError!usize { | ||||
|     // Suppress unused var warning | ||||
|     _ = context; | ||||
|     serial.writeBytes(str); | ||||
|     return str.len; | ||||
| } | ||||
|  |  | |||
|  | @ -102,15 +102,15 @@ pub fn physToVirt(phys: anytype) @TypeOf(phys) { | |||
| test "physToVirt" { | ||||
|     ADDR_OFFSET = 0xC0000000; | ||||
|     const offset: usize = ADDR_OFFSET; | ||||
|     expectEqual(physToVirt(@as(usize, 0)), offset + 0); | ||||
|     expectEqual(physToVirt(@as(usize, 123)), offset + 123); | ||||
|     expectEqual(@ptrToInt(physToVirt(@intToPtr(*align(1) usize, 123))), offset + 123); | ||||
|     try expectEqual(physToVirt(@as(usize, 0)), offset + 0); | ||||
|     try expectEqual(physToVirt(@as(usize, 123)), offset + 123); | ||||
|     try expectEqual(@ptrToInt(physToVirt(@intToPtr(*align(1) usize, 123))), offset + 123); | ||||
| } | ||||
| 
 | ||||
| test "virtToPhys" { | ||||
|     ADDR_OFFSET = 0xC0000000; | ||||
|     const offset: usize = ADDR_OFFSET; | ||||
|     expectEqual(virtToPhys(offset + 0), 0); | ||||
|     expectEqual(virtToPhys(offset + 123), 123); | ||||
|     expectEqual(@ptrToInt(virtToPhys(@intToPtr(*align(1) usize, offset + 123))), 123); | ||||
|     try expectEqual(virtToPhys(offset + 0), 0); | ||||
|     try expectEqual(virtToPhys(offset + 123), 123); | ||||
|     try expectEqual(@ptrToInt(virtToPhys(@intToPtr(*align(1) usize, offset + 123))), 123); | ||||
| } | ||||
|  |  | |||
|  | @ -1,7 +1,6 @@ | |||
| const std = @import("std"); | ||||
| const builtin = @import("builtin"); | ||||
| const builtin = std.builtin; | ||||
| const arch = @import("arch.zig").internals; | ||||
| const multiboot = @import("multiboot.zig"); | ||||
| const mem = @import("mem.zig"); | ||||
| const build_options = @import("build_options"); | ||||
| const ArrayList = std.ArrayList; | ||||
|  | @ -32,12 +31,12 @@ const SymbolMap = struct { | |||
|     /// Initialise an empty symbol map. | ||||
|     /// | ||||
|     /// Arguments: | ||||
|     ///     IN allocator: *Allocator - The allocator to use to initialise the array list. | ||||
|     ///     IN allocator: Allocator - The allocator to use to initialise the array list. | ||||
|     /// | ||||
|     /// Return: SymbolMap | ||||
|     ///     The symbol map. | ||||
|     /// | ||||
|     pub fn init(allocator: *Allocator) SymbolMap { | ||||
|     pub fn init(allocator: Allocator) SymbolMap { | ||||
|         return SymbolMap{ | ||||
|             .symbols = ArrayList(MapEntry).init(allocator), | ||||
|         }; | ||||
|  | @ -111,7 +110,7 @@ var symbol_map: ?SymbolMap = null; | |||
| /// | ||||
| fn logTraceAddress(addr: usize) void { | ||||
|     const str = if (symbol_map) |syms| syms.search(addr) orelse "?????" else "(no symbols available)"; | ||||
|     log.emerg("{x}: {s}\n", .{ addr, str }); | ||||
|     log.err("{x}: {s}\n", .{ addr, str }); | ||||
| } | ||||
| 
 | ||||
| /// | ||||
|  | @ -278,7 +277,7 @@ fn parseMapEntry(start: *[*]const u8, end: *const u8) (PanicError || std.fmt.Par | |||
| 
 | ||||
| pub fn panic(trace: ?*builtin.StackTrace, comptime format: []const u8, args: anytype) noreturn { | ||||
|     @setCold(true); | ||||
|     log.emerg("Kernel panic: " ++ format ++ "\n", args); | ||||
|     log.err("Kernel panic: " ++ format ++ "\n", args); | ||||
|     if (trace) |trc| { | ||||
|         var last_addr: u64 = 0; | ||||
|         for (trc.instruction_addresses) |ret_addr| { | ||||
|  | @ -298,20 +297,20 @@ pub fn panic(trace: ?*builtin.StackTrace, comptime format: []const u8, args: any | |||
| } | ||||
| 
 | ||||
| /// | ||||
| /// Initialise the panic subsystem by looking for a boot module called "kernel.map" and loading the | ||||
| /// symbols from it. Exits early if no such module was found. | ||||
| /// Initialise the symbol table used by the panic subsystem by looking for a boot module called "kernel.map" and loading the | ||||
| /// symbol entries from it. Exits early if no such module was found. | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN mem_profile: *const mem.MemProfile - The memory profile from which to get the loaded boot | ||||
| ///         modules. | ||||
| ///     IN allocator: *Allocator - The allocator to use to store the symbol map. | ||||
| ///     IN allocator: Allocator - The allocator to use to store the symbol map. | ||||
| /// | ||||
| /// Error: PanicError || Allocator.Error || std.fmt.ParseIntError | ||||
| ///     PanicError.InvalidSymbolFile - A terminating whitespace wasn't found before the end address. | ||||
| ///     Allocator.Error.OutOfMemory - If there wasn't enough memory. | ||||
| ///     std.fmt.ParseIntError - See parseMapEntry. | ||||
| /// | ||||
| pub fn init(mem_profile: *const mem.MemProfile, allocator: *Allocator) (PanicError || Allocator.Error || std.fmt.ParseIntError)!void { | ||||
| pub fn initSymbols(mem_profile: *const mem.MemProfile, allocator: Allocator) (PanicError || Allocator.Error || std.fmt.ParseIntError)!void { | ||||
|     log.info("Init\n", .{}); | ||||
|     defer log.info("Done\n", .{}); | ||||
| 
 | ||||
|  | @ -355,91 +354,91 @@ test "parseChar" { | |||
|     const str: []const u8 = "plutoisthebest"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var char = try parseChar(str.ptr, end); | ||||
|     testing.expectEqual(char, 'p'); | ||||
|     try testing.expectEqual(char, 'p'); | ||||
|     char = try parseChar(str.ptr + 1, end); | ||||
|     testing.expectEqual(char, 'l'); | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseChar(str.ptr + str.len, end)); | ||||
|     try testing.expectEqual(char, 'l'); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseChar(str.ptr + str.len, end)); | ||||
| } | ||||
| 
 | ||||
| test "parseWhitespace" { | ||||
|     const str: []const u8 = "    a"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = try parseWhitespace(str.ptr, end); | ||||
|     testing.expectEqual(@ptrToInt(str.ptr) + 4, @ptrToInt(ptr)); | ||||
|     try testing.expectEqual(@ptrToInt(str.ptr) + 4, @ptrToInt(ptr)); | ||||
| } | ||||
| 
 | ||||
| test "parseWhitespace fails without a terminating whitespace" { | ||||
|     const str: []const u8 = "   "; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseWhitespace(str.ptr, end)); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseWhitespace(str.ptr, end)); | ||||
| } | ||||
| 
 | ||||
| test "parseNonWhitespace" { | ||||
|     const str: []const u8 = "ab "; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = try parseNonWhitespace(str.ptr, end); | ||||
|     testing.expectEqual(@ptrToInt(str.ptr) + 2, @ptrToInt(ptr)); | ||||
|     try testing.expectEqual(@ptrToInt(str.ptr) + 2, @ptrToInt(ptr)); | ||||
| } | ||||
| 
 | ||||
| test "parseNonWhitespace fails without a terminating whitespace" { | ||||
|     const str: []const u8 = "abc"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseNonWhitespace(str.ptr, end)); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseNonWhitespace(str.ptr, end)); | ||||
| } | ||||
| 
 | ||||
| test "parseNonNewLine" { | ||||
|     const str: []const u8 = "ab\n"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = try parseNonNewLine(str.ptr, end); | ||||
|     testing.expectEqual(@ptrToInt(str.ptr) + 2, @ptrToInt(ptr)); | ||||
|     try testing.expectEqual(@ptrToInt(str.ptr) + 2, @ptrToInt(ptr)); | ||||
| } | ||||
| 
 | ||||
| test "parseNonNewLine fails without a terminating newline" { | ||||
|     const str: []const u8 = "abc"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseNonNewLine(str.ptr, end)); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseNonNewLine(str.ptr, end)); | ||||
| } | ||||
| 
 | ||||
| test "parseAddr" { | ||||
|     const str: []const u8 = "1a2b3c4d "; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectEqual(try parseAddr(&ptr, end), 0x1a2b3c4d); | ||||
|     try testing.expectEqual(try parseAddr(&ptr, end), 0x1a2b3c4d); | ||||
| } | ||||
| 
 | ||||
| test "parseAddr fails without a terminating whitespace" { | ||||
|     const str: []const u8 = "1a2b3c4d"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseAddr(&ptr, end)); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseAddr(&ptr, end)); | ||||
| } | ||||
| 
 | ||||
| test "parseAddr fails with an invalid integer" { | ||||
|     const str: []const u8 = "1g2t "; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectError(error.InvalidCharacter, parseAddr(&ptr, end)); | ||||
|     try testing.expectError(error.InvalidCharacter, parseAddr(&ptr, end)); | ||||
| } | ||||
| 
 | ||||
| test "parseName" { | ||||
|     const str: []const u8 = "func_name\n"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectEqualSlices(u8, try parseName(&ptr, end), "func_name"); | ||||
|     try testing.expectEqualSlices(u8, try parseName(&ptr, end), "func_name"); | ||||
| } | ||||
| 
 | ||||
| test "parseName with spaces" { | ||||
|     const str: []const u8 = "func_name(*const type   )\n"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectEqualSlices(u8, try parseName(&ptr, end), "func_name(*const type   )"); | ||||
|     try testing.expectEqualSlices(u8, try parseName(&ptr, end), "func_name(*const type   )"); | ||||
| } | ||||
| 
 | ||||
| test "parseName fails without a terminating newline" { | ||||
|     const str: []const u8 = "func_name"; | ||||
|     const end = @ptrCast(*const u8, str.ptr + str.len); | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseName(&ptr, end)); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseName(&ptr, end)); | ||||
| } | ||||
| 
 | ||||
| test "parseMapEntry" { | ||||
|  | @ -449,37 +448,37 @@ test "parseMapEntry" { | |||
| 
 | ||||
|     var actual = try parseMapEntry(&ptr, end); | ||||
|     var expected = MapEntry{ .addr = 0x1a2b3c4d, .func_name = "func_name" }; | ||||
|     testing.expectEqual(actual.addr, expected.addr); | ||||
|     testing.expectEqualSlices(u8, actual.func_name, expected.func_name); | ||||
|     try testing.expectEqual(actual.addr, expected.addr); | ||||
|     try testing.expectEqualSlices(u8, actual.func_name, expected.func_name); | ||||
| 
 | ||||
|     actual = try parseMapEntry(&ptr, end); | ||||
|     expected = MapEntry{ .addr = 0x5e6f7a8b, .func_name = "func_name2" }; | ||||
|     testing.expectEqual(actual.addr, expected.addr); | ||||
|     testing.expectEqualSlices(u8, actual.func_name, expected.func_name); | ||||
|     try testing.expectEqual(actual.addr, expected.addr); | ||||
|     try testing.expectEqualSlices(u8, actual.func_name, expected.func_name); | ||||
| } | ||||
| 
 | ||||
| test "parseMapEntry fails without a terminating newline" { | ||||
|     const str: []const u8 = "1a2b3c4d func_name"; | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseMapEntry(&ptr, @ptrCast(*const u8, str.ptr + 18))); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseMapEntry(&ptr, @ptrCast(*const u8, str.ptr + 18))); | ||||
| } | ||||
| 
 | ||||
| test "parseMapEntry fails without any characters" { | ||||
|     const str: []const u8 = " "; | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseMapEntry(&ptr, @ptrCast(*const u8, str.ptr))); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseMapEntry(&ptr, @ptrCast(*const u8, str.ptr))); | ||||
| } | ||||
| 
 | ||||
| test "parseMapEntry fails with an invalid address" { | ||||
|     const str: []const u8 = "xyz func_name"; | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectError(error.InvalidCharacter, parseMapEntry(&ptr, @ptrCast(*const u8, str.ptr + 13))); | ||||
|     try testing.expectError(error.InvalidCharacter, parseMapEntry(&ptr, @ptrCast(*const u8, str.ptr + 13))); | ||||
| } | ||||
| 
 | ||||
| test "parseMapEntry fails without a name" { | ||||
|     const str: []const u8 = "123 "; | ||||
|     var ptr = str.ptr; | ||||
|     testing.expectError(PanicError.InvalidSymbolFile, parseMapEntry(&ptr, @ptrCast(*const u8, str.ptr + 4))); | ||||
|     try testing.expectError(PanicError.InvalidSymbolFile, parseMapEntry(&ptr, @ptrCast(*const u8, str.ptr + 4))); | ||||
| } | ||||
| 
 | ||||
| test "SymbolMap" { | ||||
|  | @ -490,18 +489,18 @@ test "SymbolMap" { | |||
|     try map.addEntry(MapEntry{ .func_name = "def"[0..], .addr = 456 }); | ||||
|     try map.add("ghi"[0..], 789); | ||||
|     try map.addEntry(MapEntry{ .func_name = "jkl"[0..], .addr = 1010 }); | ||||
|     testing.expectEqual(map.search(54), null); | ||||
|     testing.expectEqual(map.search(122), null); | ||||
|     testing.expectEqual(map.search(123), "abc"); | ||||
|     testing.expectEqual(map.search(234), "abc"); | ||||
|     testing.expectEqual(map.search(455), "abc"); | ||||
|     testing.expectEqual(map.search(456), "def"); | ||||
|     testing.expectEqual(map.search(678), "def"); | ||||
|     testing.expectEqual(map.search(788), "def"); | ||||
|     testing.expectEqual(map.search(789), "ghi"); | ||||
|     testing.expectEqual(map.search(1009), "ghi"); | ||||
|     testing.expectEqual(map.search(1010), "jkl"); | ||||
|     testing.expectEqual(map.search(2345), "jkl"); | ||||
|     try testing.expectEqual(map.search(54), null); | ||||
|     try testing.expectEqual(map.search(122), null); | ||||
|     try testing.expectEqual(map.search(123), "abc"); | ||||
|     try testing.expectEqual(map.search(234), "abc"); | ||||
|     try testing.expectEqual(map.search(455), "abc"); | ||||
|     try testing.expectEqual(map.search(456), "def"); | ||||
|     try testing.expectEqual(map.search(678), "def"); | ||||
|     try testing.expectEqual(map.search(788), "def"); | ||||
|     try testing.expectEqual(map.search(789), "ghi"); | ||||
|     try testing.expectEqual(map.search(1009), "ghi"); | ||||
|     try testing.expectEqual(map.search(1010), "jkl"); | ||||
|     try testing.expectEqual(map.search(2345), "jkl"); | ||||
| } | ||||
| 
 | ||||
| /// | ||||
|  |  | |||
|  | @ -2,8 +2,7 @@ const is_test = @import("builtin").is_test; | |||
| const std = @import("std"); | ||||
| const log = std.log.scoped(.pmm); | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.mock_path; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig").internals; | ||||
| const arch = @import("arch.zig").internals; | ||||
| const MemProfile = @import("mem.zig").MemProfile; | ||||
| const testing = std.testing; | ||||
| const panic = @import("panic.zig").panic; | ||||
|  | @ -96,9 +95,9 @@ pub fn blocksFree() usize { | |||
| /// | ||||
| /// Arguments: | ||||
| ///     IN mem: *const MemProfile - The system's memory profile. | ||||
| ///     IN allocator: *Allocator - The allocator to use to allocate the bitmaps. | ||||
| ///     IN allocator: Allocator - The allocator to use to allocate the bitmaps. | ||||
| /// | ||||
| pub fn init(mem_profile: *const MemProfile, allocator: *Allocator) void { | ||||
| pub fn init(mem_profile: *const MemProfile, allocator: Allocator) void { | ||||
|     log.info("Init\n", .{}); | ||||
|     defer log.info("Done\n", .{}); | ||||
| 
 | ||||
|  | @ -146,13 +145,13 @@ test "alloc" { | |||
|         i += 1; | ||||
|         addr += BLOCK_SIZE; | ||||
|     }) { | ||||
|         testing.expect(!(try isSet(addr))); | ||||
|         testing.expect(alloc().? == addr); | ||||
|         testing.expect(try isSet(addr)); | ||||
|         testing.expectEqual(blocksFree(), 31 - i); | ||||
|         try testing.expect(!(try isSet(addr))); | ||||
|         try testing.expect(alloc().? == addr); | ||||
|         try testing.expect(try isSet(addr)); | ||||
|         try testing.expectEqual(blocksFree(), 31 - i); | ||||
|     } | ||||
|     // Allocation should now fail | ||||
|     testing.expect(alloc() == null); | ||||
|     try testing.expect(alloc() == null); | ||||
| } | ||||
| 
 | ||||
| test "free" { | ||||
|  | @ -162,13 +161,13 @@ test "free" { | |||
|     // Allocate and free all entries | ||||
|     inline while (i < 32) : (i += 1) { | ||||
|         const addr = alloc().?; | ||||
|         testing.expect(try isSet(addr)); | ||||
|         testing.expectEqual(blocksFree(), 31); | ||||
|         try testing.expect(try isSet(addr)); | ||||
|         try testing.expectEqual(blocksFree(), 31); | ||||
|         try free(addr); | ||||
|         testing.expectEqual(blocksFree(), 32); | ||||
|         testing.expect(!(try isSet(addr))); | ||||
|         try testing.expectEqual(blocksFree(), 32); | ||||
|         try testing.expect(!(try isSet(addr))); | ||||
|         // Double frees should be caught | ||||
|         testing.expectError(PmmError.NotAllocated, free(addr)); | ||||
|         try testing.expectError(PmmError.NotAllocated, free(addr)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -189,14 +188,14 @@ test "setAddr and isSet" { | |||
|             h += 1; | ||||
|             addr2 += BLOCK_SIZE; | ||||
|         }) { | ||||
|             testing.expect(try isSet(addr2)); | ||||
|             try testing.expect(try isSet(addr2)); | ||||
|         } | ||||
| 
 | ||||
|         testing.expectEqual(blocksFree(), num_entries - i); | ||||
|         try testing.expectEqual(blocksFree(), num_entries - i); | ||||
|         // Set the current block | ||||
|         try setAddr(addr); | ||||
|         testing.expect(try isSet(addr)); | ||||
|         testing.expectEqual(blocksFree(), num_entries - i - 1); | ||||
|         try testing.expect(try isSet(addr)); | ||||
|         try testing.expectEqual(blocksFree(), num_entries - i - 1); | ||||
| 
 | ||||
|         // Ensure all successive entries are not set | ||||
|         var j: u32 = i + 1; | ||||
|  | @ -205,7 +204,7 @@ test "setAddr and isSet" { | |||
|             j += 1; | ||||
|             addr3 += BLOCK_SIZE; | ||||
|         }) { | ||||
|             testing.expect(!try isSet(addr3)); | ||||
|             try testing.expect(!try isSet(addr3)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -215,9 +214,9 @@ test "setAddr and isSet" { | |||
| /// | ||||
| /// Arguments: | ||||
| ///     IN mem_profile: *const MemProfile - The memory profile to check for reserved memory regions. | ||||
| ///     IN/OUT allocator: *Allocator - The allocator to use when needing to create intermediate structures used for testing | ||||
| ///     IN/OUT allocator: Allocator - The allocator to use when needing to create intermediate structures used for testing | ||||
| /// | ||||
| fn runtimeTests(mem_profile: *const MemProfile, allocator: *Allocator) void { | ||||
| fn runtimeTests(mem_profile: *const MemProfile, allocator: Allocator) void { | ||||
|     // Make sure that occupied memory can't be allocated | ||||
|     var prev_alloc: usize = std.math.maxInt(usize); | ||||
|     var alloc_list = std.ArrayList(usize).init(allocator); | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ const log = std.log.scoped(.scheduler); | |||
| const builtin = @import("builtin"); | ||||
| const is_test = builtin.is_test; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.mock_path; | ||||
| const arch = @import("arch.zig").internals; | ||||
| const panic = @import("panic.zig").panic; | ||||
| const task = @import("task.zig"); | ||||
|  | @ -105,12 +104,13 @@ pub fn pickNextTask(ctx: *arch.CpuState) usize { | |||
| /// | ||||
| /// Arguments: | ||||
| ///     IN entry_point: EntryPoint - The entry point into the task. This must be a function. | ||||
| ///     IN allocator: Allocator - The allocator to use | ||||
| /// | ||||
| /// Error: Allocator.Error | ||||
| ///     OutOfMemory - If there isn't enough memory for the a task/stack. Any memory allocated will | ||||
| ///                   be freed on return. | ||||
| /// | ||||
| pub fn scheduleTask(new_task: *Task, allocator: *Allocator) Allocator.Error!void { | ||||
| pub fn scheduleTask(new_task: *Task, allocator: Allocator) Allocator.Error!void { | ||||
|     var task_node = try allocator.create(TailQueue(*Task).Node); | ||||
|     task_node.* = .{ .data = new_task }; | ||||
|     tasks.prepend(task_node); | ||||
|  | @ -123,13 +123,13 @@ pub fn scheduleTask(new_task: *Task, allocator: *Allocator) Allocator.Error!void | |||
| /// idle task for when there is no more tasks to run. | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *Allocator - The allocator to use when needing to allocate memory. | ||||
| ///     IN allocator: Allocator - The allocator to use when needing to allocate memory. | ||||
| ///     IN mem_profile: *const mem.MemProfile - The system's memory profile used for runtime testing. | ||||
| /// | ||||
| /// Error: Allocator.Error | ||||
| ///     OutOfMemory - There is no more memory. Any memory allocated will be freed on return. | ||||
| /// | ||||
| pub fn init(allocator: *Allocator, mem_profile: *const mem.MemProfile) Allocator.Error!void { | ||||
| pub fn init(allocator: Allocator, mem_profile: *const mem.MemProfile) Allocator.Error!void { | ||||
|     // TODO: Maybe move the task init here? | ||||
|     log.info("Init\n", .{}); | ||||
|     defer log.info("Done\n", .{}); | ||||
|  | @ -170,7 +170,7 @@ fn test_fn2() void {} | |||
| 
 | ||||
| var test_pid_counter: u7 = 1; | ||||
| 
 | ||||
| fn createTestTask(entry_point: EntryPoint, allocator: *Allocator, kernel: bool, task_vmm: *vmm.VirtualMemoryManager(u8)) Allocator.Error!*Task { | ||||
| fn createTestTask(allocator: Allocator) Allocator.Error!*Task { | ||||
|     var t = try allocator.create(Task); | ||||
|     errdefer allocator.destroy(t); | ||||
|     t.pid = test_pid_counter; | ||||
|  | @ -181,7 +181,7 @@ fn createTestTask(entry_point: EntryPoint, allocator: *Allocator, kernel: bool, | |||
|     return t; | ||||
| } | ||||
| 
 | ||||
| fn destroyTestTask(self: *Task, allocator: *Allocator) void { | ||||
| fn destroyTestTask(self: *Task, allocator: Allocator) void { | ||||
|     if (@ptrToInt(self.kernel_stack.ptr) != @ptrToInt(&KERNEL_STACK_START)) { | ||||
|         allocator.free(self.kernel_stack); | ||||
|     } | ||||
|  | @ -214,26 +214,26 @@ test "pickNextTask" { | |||
|     const fn1_stack_pointer = test_fn1_task.stack_pointer; | ||||
|     const fn2_stack_pointer = test_fn2_task.stack_pointer; | ||||
| 
 | ||||
|     expectEqual(pickNextTask(&ctx), fn1_stack_pointer); | ||||
|     try expectEqual(pickNextTask(&ctx), fn1_stack_pointer); | ||||
|     // The stack pointer of the re-added task should point to the context | ||||
|     expectEqual(tasks.first.?.data.stack_pointer, @ptrToInt(&ctx)); | ||||
|     try expectEqual(tasks.first.?.data.stack_pointer, @ptrToInt(&ctx)); | ||||
| 
 | ||||
|     // Should be the PID of the next task | ||||
|     expectEqual(current_task.pid, 1); | ||||
|     try expectEqual(current_task.pid, 1); | ||||
| 
 | ||||
|     expectEqual(pickNextTask(&ctx), fn2_stack_pointer); | ||||
|     try expectEqual(pickNextTask(&ctx), fn2_stack_pointer); | ||||
|     // The stack pointer of the re-added task should point to the context | ||||
|     expectEqual(tasks.first.?.data.stack_pointer, @ptrToInt(&ctx)); | ||||
|     try expectEqual(tasks.first.?.data.stack_pointer, @ptrToInt(&ctx)); | ||||
| 
 | ||||
|     // Should be the PID of the next task | ||||
|     expectEqual(current_task.pid, 2); | ||||
|     try expectEqual(current_task.pid, 2); | ||||
| 
 | ||||
|     expectEqual(pickNextTask(&ctx), @ptrToInt(&ctx)); | ||||
|     try expectEqual(pickNextTask(&ctx), @ptrToInt(&ctx)); | ||||
|     // The stack pointer of the re-added task should point to the context | ||||
|     expectEqual(tasks.first.?.data.stack_pointer, @ptrToInt(&ctx)); | ||||
|     try expectEqual(tasks.first.?.data.stack_pointer, @ptrToInt(&ctx)); | ||||
| 
 | ||||
|     // Should be back tot he beginning | ||||
|     expectEqual(current_task.pid, 0); | ||||
|     try expectEqual(current_task.pid, 0); | ||||
| 
 | ||||
|     // Reset the test pid | ||||
|     test_pid_counter = 1; | ||||
|  | @ -255,7 +255,7 @@ test "createNewTask add new task" { | |||
|     defer test_fn1_task.destroy(allocator); | ||||
|     try scheduleTask(test_fn1_task, allocator); | ||||
| 
 | ||||
|     expectEqual(tasks.len, 1); | ||||
|     try expectEqual(tasks.len, 1); | ||||
| 
 | ||||
|     // Free the memory | ||||
|     allocator.destroy(tasks.first.?); | ||||
|  | @ -266,11 +266,11 @@ test "init" { | |||
| 
 | ||||
|     try init(allocator, undefined); | ||||
| 
 | ||||
|     expectEqual(current_task.pid, 0); | ||||
|     expectEqual(@ptrToInt(current_task.kernel_stack.ptr), @ptrToInt(&KERNEL_STACK_START)); | ||||
|     expectEqual(current_task.kernel_stack.len, @ptrToInt(&KERNEL_STACK_END) - @ptrToInt(&KERNEL_STACK_START)); | ||||
|     try expectEqual(current_task.pid, 0); | ||||
|     try expectEqual(@ptrToInt(current_task.kernel_stack.ptr), @ptrToInt(&KERNEL_STACK_START)); | ||||
|     try expectEqual(current_task.kernel_stack.len, @ptrToInt(&KERNEL_STACK_END) - @ptrToInt(&KERNEL_STACK_START)); | ||||
| 
 | ||||
|     expectEqual(tasks.len, 1); | ||||
|     try expectEqual(tasks.len, 1); | ||||
| 
 | ||||
|     // Free the tasks created | ||||
|     current_task.destroy(allocator); | ||||
|  | @ -298,9 +298,9 @@ fn task_function() noreturn { | |||
| /// occurs. Also tests that a global volatile can be test in one task and be reacted to in another. | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *Allocator - The allocator to use when needing to allocate memory. | ||||
| ///     IN allocator: Allocator - The allocator to use when needing to allocate memory. | ||||
| /// | ||||
| fn rt_variable_preserved(allocator: *Allocator) void { | ||||
| fn rt_variable_preserved(allocator: Allocator) void { | ||||
|     // Create the memory for the boolean | ||||
|     is_set = allocator.create(bool) catch unreachable; | ||||
|     defer allocator.destroy(is_set); | ||||
|  | @ -353,7 +353,7 @@ fn rt_variable_preserved(allocator: *Allocator) void { | |||
| ///     IN allocator: *std.mem.Allocator - The allocator to use when intialising the task | ||||
| ///     IN mem_profile: mem.MemProfile - The system's memory profile. Determines the end address of the user task's VMM. | ||||
| /// | ||||
| fn rt_user_task(allocator: *Allocator, mem_profile: *const mem.MemProfile) void { | ||||
| fn rt_user_task(allocator: Allocator, mem_profile: *const mem.MemProfile) void { | ||||
|     for (&[_][]const u8{ "/user_program_data.elf", "/user_program.elf" }) |user_program| { | ||||
|         // 1. Create user VMM | ||||
|         var task_vmm = allocator.create(vmm.VirtualMemoryManager(arch.VmmPayload)) catch |e| { | ||||
|  | @ -369,11 +369,9 @@ fn rt_user_task(allocator: *Allocator, mem_profile: *const mem.MemProfile) void | |||
|         const code_len = user_program_file.read(code[0..code.len]) catch |e| { | ||||
|             panic(@errorReturnTrace(), "Failed to read {s}: {}\n", .{ user_program, e }); | ||||
|         }; | ||||
|         const program_elf = elf.Elf.init(code[0..code_len], builtin.arch, allocator) catch |e| panic(@errorReturnTrace(), "Failed to load {s}: {}\n", .{ user_program, e }); | ||||
|         const program_elf = elf.Elf.init(code[0..code_len], builtin.cpu.arch, allocator) catch |e| panic(@errorReturnTrace(), "Failed to load {s}: {}\n", .{ user_program, e }); | ||||
|         defer program_elf.deinit(); | ||||
| 
 | ||||
|         const current_physical_blocks = pmm.blocksFree(); | ||||
| 
 | ||||
|         var user_task = task.Task.createFromElf(program_elf, false, task_vmm, allocator) catch |e| { | ||||
|             panic(@errorReturnTrace(), "Failed to create task for {s}: {}\n", .{ user_program, e }); | ||||
|         }; | ||||
|  | @ -407,10 +405,10 @@ fn rt_user_task(allocator: *Allocator, mem_profile: *const mem.MemProfile) void | |||
| /// The scheduler runtime tests that will test the scheduling functionality. | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN allocator: *Allocator - The allocator to use when needing to allocate memory. | ||||
| ///     IN allocator: Allocator - The allocator to use when needing to allocate memory. | ||||
| ///     IN mem_profile: *const mem.MemProfile - The system's memory profile. Used to set up user task VMMs. | ||||
| /// | ||||
| fn runtimeTests(allocator: *Allocator, mem_profile: *const mem.MemProfile) void { | ||||
| fn runtimeTests(allocator: Allocator, mem_profile: *const mem.MemProfile) void { | ||||
|     arch.enableInterrupts(); | ||||
|     rt_user_task(allocator, mem_profile); | ||||
|     rt_variable_preserved(allocator); | ||||
|  |  | |||
|  | @ -98,6 +98,12 @@ pub fn handle(syscall: Syscall, arg1: usize, arg2: usize, arg3: usize, arg4: usi | |||
| } | ||||
| 
 | ||||
| pub fn handleTest1(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = arg1; | ||||
|     _ = arg2; | ||||
|     _ = arg3; | ||||
|     _ = arg4; | ||||
|     _ = arg5; | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -106,17 +112,23 @@ pub fn handleTest2(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usi | |||
| } | ||||
| 
 | ||||
| pub fn handleTest3(arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) Error!usize { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = arg1; | ||||
|     _ = arg2; | ||||
|     _ = arg3; | ||||
|     _ = arg4; | ||||
|     _ = arg5; | ||||
|     return std.mem.Allocator.Error.OutOfMemory; | ||||
| } | ||||
| 
 | ||||
| test "getHandler" { | ||||
|     std.testing.expectEqual(Syscall.Test1.getHandler(), handleTest1); | ||||
|     std.testing.expectEqual(Syscall.Test2.getHandler(), handleTest2); | ||||
|     std.testing.expectEqual(Syscall.Test3.getHandler(), handleTest3); | ||||
|     try std.testing.expectEqual(Syscall.Test1.getHandler(), handleTest1); | ||||
|     try std.testing.expectEqual(Syscall.Test2.getHandler(), handleTest2); | ||||
|     try std.testing.expectEqual(Syscall.Test3.getHandler(), handleTest3); | ||||
| } | ||||
| 
 | ||||
| test "handle" { | ||||
|     std.testing.expectEqual(@as(usize, 0), try handle(.Test1, 0, 0, 0, 0, 0)); | ||||
|     std.testing.expectEqual(@as(usize, 1 + 2 + 3 + 4 + 5), try handle(.Test2, 1, 2, 3, 4, 5)); | ||||
|     std.testing.expectError(Error.OutOfMemory, handle(.Test3, 0, 0, 0, 0, 0)); | ||||
|     try std.testing.expectEqual(@as(usize, 0), try handle(.Test1, 0, 0, 0, 0, 0)); | ||||
|     try std.testing.expectEqual(@as(usize, 1 + 2 + 3 + 4 + 5), try handle(.Test2, 1, 2, 3, 4, 5)); | ||||
|     try std.testing.expectError(Error.OutOfMemory, handle(.Test3, 0, 0, 0, 0, 0)); | ||||
| } | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ const expectError = std.testing.expectError; | |||
| const builtin = @import("builtin"); | ||||
| const is_test = builtin.is_test; | ||||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.mock_path; | ||||
| const arch = @import("arch.zig").internals; | ||||
| const panic = @import("panic.zig").panic; | ||||
| const vmm = @import("vmm.zig"); | ||||
|  | @ -68,7 +67,7 @@ pub const Task = struct { | |||
|     ///     IN entry_point: EntryPoint - The entry point into the task. This must be a function. | ||||
|     ///     IN kernel: bool              - Whether the task has kernel or user privileges. | ||||
|     ///     IN task_vmm: *VirtualMemoryManager - The virtual memory manager associated with the task. | ||||
|     ///     IN allocator: *Allocator     - The allocator for allocating memory for a task. | ||||
|     ///     IN allocator: Allocator     - The allocator for allocating memory for a task. | ||||
|     /// | ||||
|     /// Return: *Task | ||||
|     ///     Pointer to an allocated task. This will then need to be added to the task queue. | ||||
|  | @ -77,7 +76,7 @@ pub const Task = struct { | |||
|     ///     OutOfMemory - If there is no more memory to allocate. Any memory or PID allocated will | ||||
|     ///                   be freed on return. | ||||
|     /// | ||||
|     pub fn create(entry_point: EntryPoint, kernel: bool, task_vmm: *vmm.VirtualMemoryManager(arch.VmmPayload), allocator: *Allocator) Allocator.Error!*Task { | ||||
|     pub fn create(entry_point: EntryPoint, kernel: bool, task_vmm: *vmm.VirtualMemoryManager(arch.VmmPayload), allocator: Allocator) Allocator.Error!*Task { | ||||
|         var task = try allocator.create(Task); | ||||
|         errdefer allocator.destroy(task); | ||||
| 
 | ||||
|  | @ -104,7 +103,7 @@ pub const Task = struct { | |||
|         return task; | ||||
|     } | ||||
| 
 | ||||
|     pub fn createFromElf(program_elf: elf.Elf, kernel: bool, task_vmm: *vmm.VirtualMemoryManager(arch.VmmPayload), allocator: *Allocator) (bitmap.Bitmap(usize).BitmapError || vmm.VmmError || Allocator.Error)!*Task { | ||||
|     pub fn createFromElf(program_elf: elf.Elf, kernel: bool, task_vmm: *vmm.VirtualMemoryManager(arch.VmmPayload), allocator: Allocator) (bitmap.Bitmap(usize).BitmapError || vmm.VmmError || Allocator.Error)!*Task { | ||||
|         const task = try create(program_elf.header.entry_address, kernel, task_vmm, allocator); | ||||
|         errdefer task.destroy(allocator); | ||||
| 
 | ||||
|  | @ -141,8 +140,9 @@ pub const Task = struct { | |||
|     /// | ||||
|     /// Arguments: | ||||
|     ///     IN/OUT self: *Self - The pointer to self. | ||||
|     ///     IN allocator: Allocator - The allocator used to create the task. | ||||
|     /// | ||||
|     pub fn destroy(self: *Self, allocator: *Allocator) void { | ||||
|     pub fn destroy(self: *Self, allocator: Allocator) void { | ||||
|         freePid(self.pid); | ||||
|         // We need to check that the the stack has been allocated as task 0 (init) won't have a | ||||
|         // stack allocated as this in the linker script | ||||
|  | @ -182,7 +182,7 @@ fn freePid(pid: PidBitmap.IndexType) void { | |||
| 
 | ||||
| // For testing the errdefer | ||||
| const FailingAllocator = std.testing.FailingAllocator; | ||||
| const testing_allocator = &std.testing.base_allocator_instance.allocator; | ||||
| const testing_allocator = std.testing.base_allocator_instance.allocator(); | ||||
| 
 | ||||
| fn test_fn1() void {} | ||||
| 
 | ||||
|  | @ -190,28 +190,28 @@ test "create out of memory for task" { | |||
|     // Set the global allocator | ||||
|     var fa = FailingAllocator.init(testing_allocator, 0); | ||||
| 
 | ||||
|     expectError(error.OutOfMemory, Task.create(@ptrToInt(test_fn1), true, undefined, &fa.allocator)); | ||||
|     expectError(error.OutOfMemory, Task.create(@ptrToInt(test_fn1), false, undefined, &fa.allocator)); | ||||
|     try expectError(error.OutOfMemory, Task.create(@ptrToInt(test_fn1), true, undefined, fa.allocator())); | ||||
|     try expectError(error.OutOfMemory, Task.create(@ptrToInt(test_fn1), false, undefined, fa.allocator())); | ||||
| 
 | ||||
|     // Make sure any memory allocated is freed | ||||
|     expectEqual(fa.allocated_bytes, fa.freed_bytes); | ||||
|     try expectEqual(fa.allocated_bytes, fa.freed_bytes); | ||||
| 
 | ||||
|     // Make sure no PIDs were allocated | ||||
|     expectEqual(all_pids.bitmap, 0); | ||||
|     try expectEqual(all_pids.bitmap, 0); | ||||
| } | ||||
| 
 | ||||
| test "create out of memory for stack" { | ||||
|     // Set the global allocator | ||||
|     var fa = FailingAllocator.init(testing_allocator, 1); | ||||
| 
 | ||||
|     expectError(error.OutOfMemory, Task.create(@ptrToInt(test_fn1), true, undefined, &fa.allocator)); | ||||
|     expectError(error.OutOfMemory, Task.create(@ptrToInt(test_fn1), false, undefined, &fa.allocator)); | ||||
|     try expectError(error.OutOfMemory, Task.create(@ptrToInt(test_fn1), true, undefined, fa.allocator())); | ||||
|     try expectError(error.OutOfMemory, Task.create(@ptrToInt(test_fn1), false, undefined, fa.allocator())); | ||||
| 
 | ||||
|     // Make sure any memory allocated is freed | ||||
|     expectEqual(fa.allocated_bytes, fa.freed_bytes); | ||||
|     try expectEqual(fa.allocated_bytes, fa.freed_bytes); | ||||
| 
 | ||||
|     // Make sure no PIDs were allocated | ||||
|     expectEqual(all_pids.bitmap, 0); | ||||
|     try expectEqual(all_pids.bitmap, 0); | ||||
| } | ||||
| 
 | ||||
| test "create expected setup" { | ||||
|  | @ -219,15 +219,15 @@ test "create expected setup" { | |||
|     defer task.destroy(std.testing.allocator); | ||||
| 
 | ||||
|     // Will allocate the first PID 0 | ||||
|     expectEqual(task.pid, 0); | ||||
|     expectEqual(task.kernel_stack.len, STACK_SIZE); | ||||
|     expectEqual(task.user_stack.len, 0); | ||||
|     try expectEqual(task.pid, 0); | ||||
|     try expectEqual(task.kernel_stack.len, STACK_SIZE); | ||||
|     try expectEqual(task.user_stack.len, 0); | ||||
| 
 | ||||
|     var user_task = try Task.create(@ptrToInt(test_fn1), false, undefined, std.testing.allocator); | ||||
|     defer user_task.destroy(std.testing.allocator); | ||||
|     expectEqual(user_task.pid, 1); | ||||
|     expectEqual(user_task.user_stack.len, STACK_SIZE); | ||||
|     expectEqual(user_task.kernel_stack.len, STACK_SIZE); | ||||
|     try expectEqual(user_task.pid, 1); | ||||
|     try expectEqual(user_task.user_stack.len, STACK_SIZE); | ||||
|     try expectEqual(user_task.kernel_stack.len, STACK_SIZE); | ||||
| } | ||||
| 
 | ||||
| test "destroy cleans up" { | ||||
|  | @ -242,54 +242,54 @@ test "destroy cleans up" { | |||
|     user_task.destroy(allocator); | ||||
| 
 | ||||
|     // All PIDs were freed | ||||
|     expectEqual(all_pids.bitmap, 0); | ||||
|     try expectEqual(all_pids.bitmap, 0); | ||||
| } | ||||
| 
 | ||||
| test "Multiple create" { | ||||
|     var task1 = try Task.create(@ptrToInt(test_fn1), true, undefined, std.testing.allocator); | ||||
|     var task2 = try Task.create(@ptrToInt(test_fn1), true, undefined, std.testing.allocator); | ||||
| 
 | ||||
|     expectEqual(task1.pid, 0); | ||||
|     expectEqual(task2.pid, 1); | ||||
|     expectEqual(all_pids.bitmap, 3); | ||||
|     try expectEqual(task1.pid, 0); | ||||
|     try expectEqual(task2.pid, 1); | ||||
|     try expectEqual(all_pids.bitmap, 3); | ||||
| 
 | ||||
|     task1.destroy(std.testing.allocator); | ||||
| 
 | ||||
|     expectEqual(all_pids.bitmap, 2); | ||||
|     try expectEqual(all_pids.bitmap, 2); | ||||
| 
 | ||||
|     var task3 = try Task.create(@ptrToInt(test_fn1), true, undefined, std.testing.allocator); | ||||
| 
 | ||||
|     expectEqual(task3.pid, 0); | ||||
|     expectEqual(all_pids.bitmap, 3); | ||||
|     try expectEqual(task3.pid, 0); | ||||
|     try expectEqual(all_pids.bitmap, 3); | ||||
| 
 | ||||
|     task2.destroy(std.testing.allocator); | ||||
|     task3.destroy(std.testing.allocator); | ||||
| 
 | ||||
|     var user_task = try Task.create(@ptrToInt(test_fn1), false, undefined, std.testing.allocator); | ||||
| 
 | ||||
|     expectEqual(user_task.pid, 0); | ||||
|     expectEqual(all_pids.bitmap, 1); | ||||
|     try expectEqual(user_task.pid, 0); | ||||
|     try expectEqual(all_pids.bitmap, 1); | ||||
| 
 | ||||
|     user_task.destroy(std.testing.allocator); | ||||
|     expectEqual(all_pids.bitmap, 0); | ||||
|     try expectEqual(all_pids.bitmap, 0); | ||||
| } | ||||
| 
 | ||||
| test "allocatePid and freePid" { | ||||
|     expectEqual(all_pids.bitmap, 0); | ||||
|     try expectEqual(all_pids.bitmap, 0); | ||||
| 
 | ||||
|     var i: usize = 0; | ||||
|     while (i < PidBitmap.NUM_ENTRIES) : (i += 1) { | ||||
|         expectEqual(i, allocatePid()); | ||||
|         try expectEqual(i, allocatePid()); | ||||
|     } | ||||
| 
 | ||||
|     expectEqual(all_pids.bitmap, PidBitmap.BITMAP_FULL); | ||||
|     try expectEqual(all_pids.bitmap, PidBitmap.BITMAP_FULL); | ||||
| 
 | ||||
|     i = 0; | ||||
|     while (i < PidBitmap.NUM_ENTRIES) : (i += 1) { | ||||
|         freePid(@truncate(PidBitmap.IndexType, i)); | ||||
|     } | ||||
| 
 | ||||
|     expectEqual(all_pids.bitmap, 0); | ||||
|     try expectEqual(all_pids.bitmap, 0); | ||||
| } | ||||
| 
 | ||||
| test "createFromElf" { | ||||
|  | @ -300,7 +300,7 @@ test "createFromElf" { | |||
|     const code_address = 0; | ||||
|     const elf_data = try elf.testInitData(allocator, "abc123", "strings", .Executable, code_address, 0, elf.SECTION_ALLOCATABLE, 0, code_address, 0); | ||||
|     defer allocator.free(elf_data); | ||||
|     var the_elf = try elf.Elf.init(elf_data, builtin.arch, std.testing.allocator); | ||||
|     var the_elf = try elf.Elf.init(elf_data, builtin.cpu.arch, std.testing.allocator); | ||||
|     defer the_elf.deinit(); | ||||
| 
 | ||||
|     var the_vmm = try vmm.VirtualMemoryManager(arch.VmmPayload).init(0, 10000, std.testing.allocator, arch.VMM_MAPPER, arch.KERNEL_VMM_PAYLOAD); | ||||
|  | @ -308,9 +308,9 @@ test "createFromElf" { | |||
|     const task = try Task.createFromElf(the_elf, true, &the_vmm, std.testing.allocator); | ||||
|     defer task.destroy(allocator); | ||||
| 
 | ||||
|     std.testing.expectEqual(task.pid, 0); | ||||
|     std.testing.expectEqual(task.user_stack.len, 0); | ||||
|     std.testing.expectEqual(task.kernel_stack.len, STACK_SIZE); | ||||
|     try std.testing.expectEqual(task.pid, 0); | ||||
|     try std.testing.expectEqual(task.user_stack.len, 0); | ||||
|     try std.testing.expectEqual(task.kernel_stack.len, STACK_SIZE); | ||||
| } | ||||
| 
 | ||||
| test "createFromElf clean-up" { | ||||
|  | @ -321,7 +321,7 @@ test "createFromElf clean-up" { | |||
|     const code_address = 0; | ||||
|     const elf_data = try elf.testInitData(allocator, "abc123", "strings", .Executable, code_address, 0, elf.SECTION_ALLOCATABLE, 0, code_address, 0); | ||||
|     defer allocator.free(elf_data); | ||||
|     var the_elf = try elf.Elf.init(elf_data, builtin.arch, std.testing.allocator); | ||||
|     var the_elf = try elf.Elf.init(elf_data, builtin.cpu.arch, std.testing.allocator); | ||||
|     defer the_elf.deinit(); | ||||
| 
 | ||||
|     var the_vmm = try vmm.VirtualMemoryManager(arch.VmmPayload).init(0, 10000, std.testing.allocator, arch.VMM_MAPPER, arch.KERNEL_VMM_PAYLOAD); | ||||
|  | @ -331,14 +331,14 @@ test "createFromElf clean-up" { | |||
| 
 | ||||
|     // Test clean-up | ||||
|     // Test OutOfMemory | ||||
|     var allocator2 = &std.testing.FailingAllocator.init(allocator, 0).allocator; | ||||
|     std.testing.expectError(std.mem.Allocator.Error.OutOfMemory, Task.createFromElf(the_elf, true, &the_vmm, allocator2)); | ||||
|     std.testing.expectEqual(all_pids.num_free_entries, PidBitmap.NUM_ENTRIES - 1); | ||||
|     var allocator2 = std.testing.FailingAllocator.init(allocator, 0).allocator(); | ||||
|     try std.testing.expectError(std.mem.Allocator.Error.OutOfMemory, Task.createFromElf(the_elf, true, &the_vmm, allocator2)); | ||||
|     try std.testing.expectEqual(all_pids.num_free_entries, PidBitmap.NUM_ENTRIES - 1); | ||||
|     // Test AlreadyAllocated | ||||
|     std.testing.expectError(error.AlreadyAllocated, Task.createFromElf(the_elf, true, &the_vmm, allocator)); | ||||
|     try std.testing.expectError(error.AlreadyAllocated, Task.createFromElf(the_elf, true, &the_vmm, allocator)); | ||||
|     // Test OutOfBounds | ||||
|     the_elf.section_headers[0].virtual_address = the_vmm.end + 1; | ||||
|     std.testing.expectError(error.OutOfBounds, Task.createFromElf(the_elf, true, &the_vmm, allocator)); | ||||
|     try std.testing.expectError(error.OutOfBounds, Task.createFromElf(the_elf, true, &the_vmm, allocator)); | ||||
| 
 | ||||
|     // Test errdefer clean-up by fillng up all but one block in the VMM so allocating the last section fails | ||||
|     // The allocation for the first section should be cleaned up in case of an error | ||||
|  | @ -348,5 +348,5 @@ test "createFromElf clean-up" { | |||
|     try the_vmm.free(available_address); | ||||
|     // Make the strings section allocatable so createFromElf tries to allocate more than one | ||||
|     the_elf.section_headers[1].flags |= elf.SECTION_ALLOCATABLE; | ||||
|     std.testing.expectError(error.AlreadyAllocated, Task.createFromElf(the_elf, true, &the_vmm, std.testing.allocator)); | ||||
|     try std.testing.expectError(error.AlreadyAllocated, Task.createFromElf(the_elf, true, &the_vmm, std.testing.allocator)); | ||||
| } | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ pub const TTY = struct { | |||
| 
 | ||||
| /// The current tty stream | ||||
| var tty: TTY = undefined; | ||||
| var allocator: *Allocator = undefined; | ||||
| var allocator: Allocator = undefined; | ||||
| 
 | ||||
| /// | ||||
| /// A call back function for use in the formation of a string. This calls the architecture's print function. | ||||
|  | @ -37,6 +37,8 @@ var allocator: *Allocator = undefined; | |||
| ///     The number of characters printed | ||||
| /// | ||||
| fn printCallback(ctx: void, str: []const u8) !usize { | ||||
|     // Suppress unused var warning | ||||
|     _ = ctx; | ||||
|     tty.print(str) catch |e| panic(@errorReturnTrace(), "Failed to print to tty: {}\n", .{e}); | ||||
|     return str.len; | ||||
| } | ||||
|  | @ -52,7 +54,7 @@ fn printCallback(ctx: void, str: []const u8) !usize { | |||
| pub fn print(comptime format: []const u8, args: anytype) void { | ||||
|     // Printing can't error because of the scrolling, if it does, we have a big problem | ||||
|     fmt.format(Writer{ .context = {} }, format, args) catch |e| { | ||||
|         log.emerg("Error printing. Error: {}\n", .{e}); | ||||
|         log.err("Error printing. Error: {}\n", .{e}); | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  | @ -98,10 +100,10 @@ pub fn clear() void { | |||
| /// Initialise the TTY. The details of which are up to the architecture | ||||
| /// | ||||
| /// Arguments: | ||||
| ///     IN alloc: *std.mem.Allocator - The allocator to use when requiring memory | ||||
| ///     IN alloc: Allocator - The allocator to use when requiring memory | ||||
| ///     IN boot_payload: arch.BootPayload - The payload passed to the kernel on boot | ||||
| /// | ||||
| pub fn init(alloc: *Allocator, boot_payload: arch.BootPayload) void { | ||||
| pub fn init(alloc: Allocator, boot_payload: arch.BootPayload) void { | ||||
|     log.info("Init\n", .{}); | ||||
|     defer log.info("Done\n", .{}); | ||||
|     tty = arch.initTTY(boot_payload); | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| const build_options = @import("build_options"); | ||||
| const mock_path = build_options.mock_path; | ||||
| const builtin = @import("builtin"); | ||||
| const builtin = std.builtin; | ||||
| const is_test = builtin.is_test; | ||||
| const std = @import("std"); | ||||
| const log = std.log.scoped(.vmm); | ||||
|  | @ -9,8 +9,9 @@ const pmm = @import("pmm.zig"); | |||
| const mem = @import("mem.zig"); | ||||
| const tty = @import("tty.zig"); | ||||
| const panic = @import("panic.zig").panic; | ||||
| const arch = if (is_test) @import(mock_path ++ "arch_mock.zig") else @import("arch.zig").internals; | ||||
| const arch = @import("arch.zig").internals; | ||||
| const Allocator = std.mem.Allocator; | ||||
| const assert = std.debug.assert; | ||||
| 
 | ||||
| /// Attributes for a virtual memory allocation | ||||
| pub const Attributes = struct { | ||||
|  | @ -71,7 +72,7 @@ pub fn Mapper(comptime Payload: type) type { | |||
|         /// Error: AllocatorError || MapperError | ||||
|         ///     The causes depend on the mapper used | ||||
|         /// | ||||
|         mapFn: fn (virtual_start: usize, virtual_end: usize, physical_start: usize, physical_end: usize, attrs: Attributes, allocator: *Allocator, spec: Payload) (Allocator.Error || MapperError)!void, | ||||
|         mapFn: fn (virtual_start: usize, virtual_end: usize, physical_start: usize, physical_end: usize, attrs: Attributes, allocator: Allocator, spec: Payload) (Allocator.Error || MapperError)!void, | ||||
| 
 | ||||
|         /// | ||||
|         /// Unmap a region (can span more than one block) of virtual memory from its physical memory. After a call to this function, the memory should not be accessible without error. | ||||
|  | @ -85,7 +86,7 @@ pub fn Mapper(comptime Payload: type) type { | |||
|         /// Error: MapperError | ||||
|         ///     The causes depend on the mapper used | ||||
|         /// | ||||
|         unmapFn: fn (virtual_start: usize, virtual_end: usize, allocator: *Allocator, spec: Payload) MapperError!void, | ||||
|         unmapFn: fn (virtual_start: usize, virtual_end: usize, allocator: Allocator, spec: Payload) MapperError!void, | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  | @ -141,7 +142,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|         end: usize, | ||||
| 
 | ||||
|         /// The allocator to use when allocating and freeing regions | ||||
|         allocator: *Allocator, | ||||
|         allocator: Allocator, | ||||
| 
 | ||||
|         /// All allocations that have been made with this manager | ||||
|         allocations: std.hash_map.AutoHashMap(usize, Allocation), | ||||
|  | @ -160,7 +161,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|         /// Arguments: | ||||
|         ///     IN start: usize - The start of the memory region to manage | ||||
|         ///     IN end: usize - The end of the memory region to manage. Must be greater than the start | ||||
|         ///     IN/OUT allocator: *Allocator - The allocator to use when allocating and freeing regions | ||||
|         ///     IN/OUT allocator: Allocator - The allocator to use when allocating and freeing regions | ||||
|         ///     IN mapper: Mapper - The mapper to use when allocating and freeing regions | ||||
|         ///     IN payload: Payload - The payload data to be passed to the mapper | ||||
|         /// | ||||
|  | @ -170,7 +171,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|         /// Error: Allocator.Error | ||||
|         ///     error.OutOfMemory - The allocator cannot allocate the memory required | ||||
|         /// | ||||
|         pub fn init(start: usize, end: usize, allocator: *Allocator, mapper: Mapper(Payload), payload: Payload) Allocator.Error!Self { | ||||
|         pub fn init(start: usize, end: usize, allocator: Allocator, mapper: Mapper(Payload), payload: Payload) Allocator.Error!Self { | ||||
|             const size = end - start; | ||||
|             var bmp = try bitmap.Bitmap(usize).init(std.mem.alignForward(size, pmm.BLOCK_SIZE) / pmm.BLOCK_SIZE, allocator); | ||||
|             return Self{ | ||||
|  | @ -209,10 +210,10 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|             var it = self.allocations.iterator(); | ||||
|             while (it.next()) |entry| { | ||||
|                 var list = std.ArrayList(usize).init(self.allocator); | ||||
|                 for (entry.value.physical.items) |block| { | ||||
|                 for (entry.value_ptr.physical.items) |block| { | ||||
|                     _ = try list.append(block); | ||||
|                 } | ||||
|                 _ = try clone.allocations.put(entry.key, Allocation{ .physical = list }); | ||||
|                 _ = try clone.allocations.put(entry.key_ptr.*, Allocation{ .physical = list }); | ||||
|             } | ||||
|             return clone; | ||||
|         } | ||||
|  | @ -227,7 +228,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|             self.bmp.deinit(); | ||||
|             var it = self.allocations.iterator(); | ||||
|             while (it.next()) |entry| { | ||||
|                 entry.value.physical.deinit(); | ||||
|                 entry.value_ptr.physical.deinit(); | ||||
|             } | ||||
|             self.allocations.deinit(); | ||||
|         } | ||||
|  | @ -248,9 +249,9 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|         pub fn virtToPhys(self: *const Self, virt: usize) VmmError!usize { | ||||
|             var it = self.allocations.iterator(); | ||||
|             while (it.next()) |entry| { | ||||
|                 const vaddr = entry.key; | ||||
|                 const vaddr = entry.key_ptr.*; | ||||
| 
 | ||||
|                 const allocation = entry.value; | ||||
|                 const allocation = entry.value_ptr.*; | ||||
|                 // If this allocation range covers the virtual address then figure out the corresponding physical block | ||||
|                 if (vaddr <= virt and vaddr + (allocation.physical.items.len * BLOCK_SIZE) > virt) { | ||||
|                     const block_number = (virt - vaddr) / BLOCK_SIZE; | ||||
|  | @ -277,8 +278,8 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|         pub fn physToVirt(self: *const Self, phys: usize) VmmError!usize { | ||||
|             var it = self.allocations.iterator(); | ||||
|             while (it.next()) |entry| { | ||||
|                 const vaddr = entry.key; | ||||
|                 const allocation = entry.value; | ||||
|                 const vaddr = entry.key_ptr.*; | ||||
|                 const allocation = entry.value_ptr.*; | ||||
| 
 | ||||
|                 for (allocation.physical.items) |block, i| { | ||||
|                     if (block <= phys and block + BLOCK_SIZE > phys) { | ||||
|  | @ -401,7 +402,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|                 // Allocate from a specific entry if the caller requested it | ||||
|                 if (self.bmp.setContiguous(num, if (virtual_addr) |a| (a - self.start) / BLOCK_SIZE else null)) |entry| { | ||||
|                     var block_list = std.ArrayList(usize).init(self.allocator); | ||||
|                     try block_list.ensureCapacity(num); | ||||
|                     try block_list.ensureUnusedCapacity(num); | ||||
| 
 | ||||
|                     var i: usize = 0; | ||||
|                     const vaddr_start = self.start + entry * BLOCK_SIZE; | ||||
|  | @ -452,8 +453,8 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|             defer blocks.deinit(); | ||||
|             var it = other.allocations.iterator(); | ||||
|             while (it.next()) |allocation| { | ||||
|                 const virtual = allocation.key; | ||||
|                 const physical = allocation.value.physical.items; | ||||
|                 const virtual = allocation.key_ptr.*; | ||||
|                 const physical = allocation.value_ptr.*.physical.items; | ||||
|                 if (start_addr >= virtual and virtual + physical.len * BLOCK_SIZE >= end_addr) { | ||||
|                     const first_block_idx = (start_addr - virtual) / BLOCK_SIZE; | ||||
|                     const last_block_idx = (end_addr - virtual) / BLOCK_SIZE; | ||||
|  | @ -532,7 +533,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
|                     panic(@errorReturnTrace(), "Failed to unmap VMM reserved memory from 0x{X} to 0x{X}: {}\n", .{ region_start, region_end, e }); | ||||
|                 }; | ||||
|                 // The allocation is freed so remove from the map | ||||
|                 self.allocations.removeAssertDiscard(vaddr); | ||||
|                 assert(self.allocations.remove(vaddr)); | ||||
|             } else { | ||||
|                 return VmmError.NotAllocated; | ||||
|             } | ||||
|  | @ -545,7 +546,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
| /// | ||||
| /// Arguments: | ||||
| ///     IN mem_profile: *const mem.MemProfile - The system's memory profile. This is used to find the kernel code region and boot modules | ||||
| ///     IN/OUT allocator: *Allocator - The allocator to use when needing to allocate memory | ||||
| ///     IN/OUT allocator: Allocator - The allocator to use when needing to allocate memory | ||||
| /// | ||||
| /// Return: VirtualMemoryManager | ||||
| ///     The virtual memory manager created with all reserved virtual regions allocated | ||||
|  | @ -553,7 +554,7 @@ pub fn VirtualMemoryManager(comptime Payload: type) type { | |||
| /// Error: Allocator.Error | ||||
| ///     error.OutOfMemory - The allocator cannot allocate the memory required | ||||
| /// | ||||
| pub fn init(mem_profile: *const mem.MemProfile, allocator: *Allocator) Allocator.Error!*VirtualMemoryManager(arch.VmmPayload) { | ||||
| pub fn init(mem_profile: *const mem.MemProfile, allocator: Allocator) Allocator.Error!*VirtualMemoryManager(arch.VmmPayload) { | ||||
|     log.info("Init\n", .{}); | ||||
|     defer log.info("Done\n", .{}); | ||||
| 
 | ||||
|  | @ -595,13 +596,13 @@ test "virtToPhys" { | |||
|     try vmm.set(.{ .start = vstart, .end = vstart + BLOCK_SIZE }, mem.Range{ .start = pstart + BLOCK_SIZE * 2, .end = pend }, .{ .kernel = true, .writable = true, .cachable = true }); | ||||
|     try vmm.set(.{ .start = vstart + BLOCK_SIZE, .end = vend }, mem.Range{ .start = pstart, .end = pstart + BLOCK_SIZE * 2 }, .{ .kernel = true, .writable = true, .cachable = true }); | ||||
| 
 | ||||
|     std.testing.expectEqual(pstart + BLOCK_SIZE * 2, try vmm.virtToPhys(vstart)); | ||||
|     std.testing.expectEqual(pstart + BLOCK_SIZE * 2 + 29, (try vmm.virtToPhys(vstart + 29))); | ||||
|     std.testing.expectEqual(pstart + 29, (try vmm.virtToPhys(vstart + BLOCK_SIZE + 29))); | ||||
|     try std.testing.expectEqual(pstart + BLOCK_SIZE * 2, try vmm.virtToPhys(vstart)); | ||||
|     try std.testing.expectEqual(pstart + BLOCK_SIZE * 2 + 29, (try vmm.virtToPhys(vstart + 29))); | ||||
|     try std.testing.expectEqual(pstart + 29, (try vmm.virtToPhys(vstart + BLOCK_SIZE + 29))); | ||||
| 
 | ||||
|     std.testing.expectError(VmmError.NotAllocated, vmm.virtToPhys(vstart - 1)); | ||||
|     std.testing.expectError(VmmError.NotAllocated, vmm.virtToPhys(vend)); | ||||
|     std.testing.expectError(VmmError.NotAllocated, vmm.virtToPhys(vend + 1)); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, vmm.virtToPhys(vstart - 1)); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, vmm.virtToPhys(vend)); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, vmm.virtToPhys(vend + 1)); | ||||
| } | ||||
| 
 | ||||
| test "physToVirt" { | ||||
|  | @ -618,13 +619,13 @@ test "physToVirt" { | |||
|     try vmm.set(.{ .start = vstart, .end = vstart + BLOCK_SIZE }, mem.Range{ .start = pstart + BLOCK_SIZE * 2, .end = pend }, .{ .kernel = true, .writable = true, .cachable = true }); | ||||
|     try vmm.set(.{ .start = vstart + BLOCK_SIZE, .end = vend }, mem.Range{ .start = pstart, .end = pstart + BLOCK_SIZE * 2 }, .{ .kernel = true, .writable = true, .cachable = true }); | ||||
| 
 | ||||
|     std.testing.expectEqual(vstart, try vmm.physToVirt(pstart + BLOCK_SIZE * 2)); | ||||
|     std.testing.expectEqual(vstart + 29, (try vmm.physToVirt(pstart + BLOCK_SIZE * 2 + 29))); | ||||
|     std.testing.expectEqual(vstart + BLOCK_SIZE + 29, (try vmm.physToVirt(pstart + 29))); | ||||
|     try std.testing.expectEqual(vstart, try vmm.physToVirt(pstart + BLOCK_SIZE * 2)); | ||||
|     try std.testing.expectEqual(vstart + 29, (try vmm.physToVirt(pstart + BLOCK_SIZE * 2 + 29))); | ||||
|     try std.testing.expectEqual(vstart + BLOCK_SIZE + 29, (try vmm.physToVirt(pstart + 29))); | ||||
| 
 | ||||
|     std.testing.expectError(VmmError.NotAllocated, vmm.physToVirt(pstart - 1)); | ||||
|     std.testing.expectError(VmmError.NotAllocated, vmm.physToVirt(pend)); | ||||
|     std.testing.expectError(VmmError.NotAllocated, vmm.physToVirt(pend + 1)); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, vmm.physToVirt(pstart - 1)); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, vmm.physToVirt(pend)); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, vmm.physToVirt(pend + 1)); | ||||
| } | ||||
| 
 | ||||
| test "alloc and free" { | ||||
|  | @ -645,11 +646,11 @@ test "alloc and free" { | |||
|         var should_be_set = true; | ||||
|         if (entry + num_to_alloc > num_entries) { | ||||
|             // If the number to allocate exceeded the number of entries, then allocation should have failed | ||||
|             std.testing.expectEqual(@as(?usize, null), result); | ||||
|             try std.testing.expectEqual(@as(?usize, null), result); | ||||
|             should_be_set = false; | ||||
|         } else { | ||||
|             // Else it should have succeeded and allocated the correct address | ||||
|             std.testing.expectEqual(@as(?usize, vmm.start + entry * BLOCK_SIZE), result); | ||||
|             try std.testing.expectEqual(@as(?usize, vmm.start + entry * BLOCK_SIZE), result); | ||||
|             try virtual_allocations.append(result.?); | ||||
|         } | ||||
| 
 | ||||
|  | @ -658,20 +659,20 @@ test "alloc and free" { | |||
|         while (vaddr < (entry + num_to_alloc) * BLOCK_SIZE) : (vaddr += BLOCK_SIZE) { | ||||
|             if (should_be_set) { | ||||
|                 // Allocation succeeded so this address should be set | ||||
|                 std.testing.expect(try vmm.isSet(vaddr)); | ||||
|                 try std.testing.expect(try vmm.isSet(vaddr)); | ||||
|                 // The test mapper should have received this address | ||||
|                 std.testing.expect(try allocations.isSet(vaddr / BLOCK_SIZE)); | ||||
|                 try std.testing.expect(try allocations.isSet(vaddr / BLOCK_SIZE)); | ||||
|             } else { | ||||
|                 // Allocation failed as there weren't enough free entries | ||||
|                 if (vaddr >= num_entries * BLOCK_SIZE) { | ||||
|                     // If this address is beyond the VMM's end address, it should be out of bounds | ||||
|                     std.testing.expectError(bitmap.Bitmap(u32).BitmapError.OutOfBounds, vmm.isSet(vaddr)); | ||||
|                     std.testing.expectError(bitmap.Bitmap(u64).BitmapError.OutOfBounds, allocations.isSet(vaddr / BLOCK_SIZE)); | ||||
|                     try std.testing.expectError(bitmap.Bitmap(u32).BitmapError.OutOfBounds, vmm.isSet(vaddr)); | ||||
|                     try std.testing.expectError(bitmap.Bitmap(u64).BitmapError.OutOfBounds, allocations.isSet(vaddr / BLOCK_SIZE)); | ||||
|                 } else { | ||||
|                     // Else it should not be set | ||||
|                     std.testing.expect(!(try vmm.isSet(vaddr))); | ||||
|                     try std.testing.expect(!(try vmm.isSet(vaddr))); | ||||
|                     // The test mapper should not have received this address | ||||
|                     std.testing.expect(!(try allocations.isSet(vaddr / BLOCK_SIZE))); | ||||
|                     try std.testing.expect(!(try allocations.isSet(vaddr / BLOCK_SIZE))); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | @ -680,31 +681,31 @@ test "alloc and free" { | |||
|         // All later entries should not be set | ||||
|         var later_entry = entry; | ||||
|         while (later_entry < num_entries) : (later_entry += 1) { | ||||
|             std.testing.expect(!(try vmm.isSet(vmm.start + later_entry * BLOCK_SIZE))); | ||||
|             std.testing.expect(!(try pmm.isSet(later_entry * BLOCK_SIZE))); | ||||
|             try std.testing.expect(!(try vmm.isSet(vmm.start + later_entry * BLOCK_SIZE))); | ||||
|             try std.testing.expect(!(try pmm.isSet(later_entry * BLOCK_SIZE))); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Try freeing all allocations | ||||
|     for (virtual_allocations.items) |alloc| { | ||||
|         const alloc_group = vmm.allocations.get(alloc); | ||||
|         std.testing.expect(alloc_group != null); | ||||
|         try std.testing.expect(alloc_group != null); | ||||
|         const physical = alloc_group.?.physical; | ||||
|         // We need to create a copy of the physical allocations since the free call deinits them | ||||
|         var physical_copy = std.ArrayList(usize).init(std.testing.allocator); | ||||
|         defer physical_copy.deinit(); | ||||
|         // Make sure they are all reserved in the PMM | ||||
|         for (physical.items) |phys| { | ||||
|             std.testing.expect(try pmm.isSet(phys)); | ||||
|             try std.testing.expect(try pmm.isSet(phys)); | ||||
|             try physical_copy.append(phys); | ||||
|         } | ||||
|         vmm.free(alloc) catch unreachable; | ||||
|         // This virtual allocation should no longer be in the hashmap | ||||
|         std.testing.expectEqual(vmm.allocations.get(alloc), null); | ||||
|         std.testing.expect(!try vmm.isSet(alloc)); | ||||
|         try std.testing.expectEqual(vmm.allocations.get(alloc), null); | ||||
|         try std.testing.expect(!try vmm.isSet(alloc)); | ||||
|         // And all its physical blocks should now be free | ||||
|         for (physical_copy.items) |phys| { | ||||
|             std.testing.expect(!try pmm.isSet(phys)); | ||||
|             try std.testing.expect(!try pmm.isSet(phys)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -716,24 +717,24 @@ test "alloc at a specific address" { | |||
| 
 | ||||
|     const attrs = Attributes{ .writable = true, .cachable = true, .kernel = true }; | ||||
|     // Try allocating at the start | ||||
|     std.testing.expectEqual(vmm.alloc(10, vmm.start, attrs), vmm.start); | ||||
|     try std.testing.expectEqual(vmm.alloc(10, vmm.start, attrs), vmm.start); | ||||
|     // Try that again | ||||
|     std.testing.expectEqual(vmm.alloc(5, vmm.start, attrs), null); | ||||
|     try std.testing.expectEqual(vmm.alloc(5, vmm.start, attrs), null); | ||||
|     const middle = vmm.start + (vmm.end - vmm.start) / 2; | ||||
|     // Try allocating at the middle | ||||
|     std.testing.expectEqual(vmm.alloc(num_entries / 2, middle, attrs), middle); | ||||
|     try std.testing.expectEqual(vmm.alloc(num_entries / 2, middle, attrs), middle); | ||||
|     // Allocating after the start and colliding with the middle should be impossible | ||||
|     std.testing.expectEqual(vmm.alloc(num_entries / 2, vmm.start + 10 * BLOCK_SIZE, attrs), null); | ||||
|     try std.testing.expectEqual(vmm.alloc(num_entries / 2, vmm.start + 10 * BLOCK_SIZE, attrs), null); | ||||
|     // Allocating within the last half should be impossible | ||||
|     std.testing.expectEqual(vmm.alloc(num_entries / 4, middle + BLOCK_SIZE, attrs), null); | ||||
|     try std.testing.expectEqual(vmm.alloc(num_entries / 4, middle + BLOCK_SIZE, attrs), null); | ||||
|     // It should still be possible to allocate between the start and middle | ||||
|     std.testing.expectEqual(vmm.alloc(num_entries / 2 - 10, vmm.start + 10 * BLOCK_SIZE, attrs), vmm.start + 10 * BLOCK_SIZE); | ||||
|     try std.testing.expectEqual(vmm.alloc(num_entries / 2 - 10, vmm.start + 10 * BLOCK_SIZE, attrs), vmm.start + 10 * BLOCK_SIZE); | ||||
|     // It should now be full | ||||
|     std.testing.expectEqual(vmm.bmp.num_free_entries, 0); | ||||
|     try std.testing.expectEqual(vmm.bmp.num_free_entries, 0); | ||||
| 
 | ||||
|     // Allocating at the end and before the start should fail | ||||
|     std.testing.expectEqual(vmm.alloc(1, vmm.end, attrs), null); | ||||
|     std.testing.expectEqual(vmm.alloc(1, vmm.start - BLOCK_SIZE, attrs), null); | ||||
|     try std.testing.expectEqual(vmm.alloc(1, vmm.end, attrs), null); | ||||
|     try std.testing.expectEqual(vmm.alloc(1, vmm.start - BLOCK_SIZE, attrs), null); | ||||
| } | ||||
| 
 | ||||
| test "set" { | ||||
|  | @ -748,21 +749,21 @@ test "set" { | |||
|     const attrs = Attributes{ .kernel = true, .writable = true, .cachable = true }; | ||||
|     try vmm.set(.{ .start = vstart, .end = vend }, mem.Range{ .start = pstart, .end = pend }, attrs); | ||||
|     // Make sure it put the correct address in the map | ||||
|     std.testing.expect(vmm.allocations.get(vstart) != null); | ||||
|     try std.testing.expect(vmm.allocations.get(vstart) != null); | ||||
| 
 | ||||
|     var allocations = test_allocations.?; | ||||
|     // The entries before the virtual start shouldn't be set | ||||
|     var vaddr = vmm.start; | ||||
|     while (vaddr < vstart) : (vaddr += BLOCK_SIZE) { | ||||
|         std.testing.expect(!(try allocations.isSet((vaddr - vmm.start) / BLOCK_SIZE))); | ||||
|         try std.testing.expect(!(try allocations.isSet((vaddr - vmm.start) / BLOCK_SIZE))); | ||||
|     } | ||||
|     // The entries up until the virtual end should be set | ||||
|     while (vaddr < vend) : (vaddr += BLOCK_SIZE) { | ||||
|         std.testing.expect(try allocations.isSet((vaddr - vmm.start) / BLOCK_SIZE)); | ||||
|         try std.testing.expect(try allocations.isSet((vaddr - vmm.start) / BLOCK_SIZE)); | ||||
|     } | ||||
|     // The entries after the virtual end should not be set | ||||
|     while (vaddr < vmm.end) : (vaddr += BLOCK_SIZE) { | ||||
|         std.testing.expect(!(try allocations.isSet((vaddr - vmm.start) / BLOCK_SIZE))); | ||||
|         try std.testing.expect(!(try allocations.isSet((vaddr - vmm.start) / BLOCK_SIZE))); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -772,37 +773,37 @@ test "copy" { | |||
|     defer testDeinit(&vmm); | ||||
| 
 | ||||
|     const attrs = .{ .kernel = true, .cachable = true, .writable = true }; | ||||
|     const alloc0 = (try vmm.alloc(24, null, attrs)).?; | ||||
|     _ = (try vmm.alloc(24, null, attrs)).?; | ||||
| 
 | ||||
|     var mirrored = try vmm.copy(); | ||||
|     defer mirrored.deinit(); | ||||
|     std.testing.expectEqual(vmm.bmp.num_free_entries, mirrored.bmp.num_free_entries); | ||||
|     std.testing.expectEqual(vmm.start, mirrored.start); | ||||
|     std.testing.expectEqual(vmm.end, mirrored.end); | ||||
|     std.testing.expectEqual(vmm.allocations.count(), mirrored.allocations.count()); | ||||
|     try std.testing.expectEqual(vmm.bmp.num_free_entries, mirrored.bmp.num_free_entries); | ||||
|     try std.testing.expectEqual(vmm.start, mirrored.start); | ||||
|     try std.testing.expectEqual(vmm.end, mirrored.end); | ||||
|     try std.testing.expectEqual(vmm.allocations.count(), mirrored.allocations.count()); | ||||
|     var it = vmm.allocations.iterator(); | ||||
|     while (it.next()) |next| { | ||||
|         for (mirrored.allocations.get(next.key).?.physical.items) |block, i| { | ||||
|             std.testing.expectEqual(block, vmm.allocations.get(next.key).?.physical.items[i]); | ||||
|         for (mirrored.allocations.get(next.key_ptr.*).?.physical.items) |block, i| { | ||||
|             try std.testing.expectEqual(block, vmm.allocations.get(next.key_ptr.*).?.physical.items[i]); | ||||
|         } | ||||
|     } | ||||
|     std.testing.expectEqual(vmm.mapper, mirrored.mapper); | ||||
|     std.testing.expectEqual(vmm.payload, mirrored.payload); | ||||
|     try std.testing.expectEqual(vmm.mapper, mirrored.mapper); | ||||
|     try std.testing.expectEqual(vmm.payload, mirrored.payload); | ||||
| 
 | ||||
|     // Allocating in the new VMM shouldn't allocate in the mirrored one | ||||
|     const alloc1 = (try mirrored.alloc(3, null, attrs)).?; | ||||
|     std.testing.expectEqual(vmm.allocations.count() + 1, mirrored.allocations.count()); | ||||
|     std.testing.expectEqual(vmm.bmp.num_free_entries - 3, mirrored.bmp.num_free_entries); | ||||
|     std.testing.expectError(VmmError.NotAllocated, vmm.virtToPhys(alloc1)); | ||||
|     try std.testing.expectEqual(vmm.allocations.count() + 1, mirrored.allocations.count()); | ||||
|     try std.testing.expectEqual(vmm.bmp.num_free_entries - 3, mirrored.bmp.num_free_entries); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, vmm.virtToPhys(alloc1)); | ||||
| 
 | ||||
|     // And vice-versa | ||||
|     const alloc2 = (try vmm.alloc(3, null, attrs)).?; | ||||
|     _ = (try vmm.alloc(3, null, attrs)).?; | ||||
|     const alloc3 = (try vmm.alloc(1, null, attrs)).?; | ||||
|     const alloc4 = (try vmm.alloc(1, null, attrs)).?; | ||||
|     std.testing.expectEqual(vmm.allocations.count() - 2, mirrored.allocations.count()); | ||||
|     std.testing.expectEqual(vmm.bmp.num_free_entries + 2, mirrored.bmp.num_free_entries); | ||||
|     std.testing.expectError(VmmError.NotAllocated, mirrored.virtToPhys(alloc3)); | ||||
|     std.testing.expectError(VmmError.NotAllocated, mirrored.virtToPhys(alloc4)); | ||||
|     try std.testing.expectEqual(vmm.allocations.count() - 2, mirrored.allocations.count()); | ||||
|     try std.testing.expectEqual(vmm.bmp.num_free_entries + 2, mirrored.bmp.num_free_entries); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, mirrored.virtToPhys(alloc3)); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, mirrored.virtToPhys(alloc4)); | ||||
| } | ||||
| 
 | ||||
| test "copyData from" { | ||||
|  | @ -820,21 +821,21 @@ test "copyData from" { | |||
| 
 | ||||
|     // Make sure they are the same | ||||
|     var buff2 = @intToPtr([*]u8, alloc)[0..buff.len]; | ||||
|     std.testing.expectEqualSlices(u8, buff[0..buff.len], buff2); | ||||
|     std.testing.expectEqual(vmm_free_entries, vmm.bmp.num_free_entries); | ||||
|     try std.testing.expectEqualSlices(u8, buff[0..buff.len], buff2); | ||||
|     try std.testing.expectEqual(vmm_free_entries, vmm.bmp.num_free_entries); | ||||
|     // TODO Remove the subtraction by one once we are able to free the temp space in copyData | ||||
|     std.testing.expectEqual(vmm2_free_entries - 1, vmm2.bmp.num_free_entries); | ||||
|     try std.testing.expectEqual(vmm2_free_entries - 1, vmm2.bmp.num_free_entries); | ||||
| 
 | ||||
|     // Test NotAllocated | ||||
|     std.testing.expectError(VmmError.NotAllocated, vmm2.copyData(&vmm, true, buff[0..buff.len], alloc + alloc1_blocks * BLOCK_SIZE)); | ||||
|     std.testing.expectEqual(vmm_free_entries, vmm.bmp.num_free_entries); | ||||
|     std.testing.expectEqual(vmm2_free_entries - 1, vmm2.bmp.num_free_entries); | ||||
|     try std.testing.expectError(VmmError.NotAllocated, vmm2.copyData(&vmm, true, buff[0..buff.len], alloc + alloc1_blocks * BLOCK_SIZE)); | ||||
|     try std.testing.expectEqual(vmm_free_entries, vmm.bmp.num_free_entries); | ||||
|     try std.testing.expectEqual(vmm2_free_entries - 1, vmm2.bmp.num_free_entries); | ||||
| 
 | ||||
|     // Test Bitmap.Error.OutOfBounds | ||||
|     std.testing.expectError(bitmap.Bitmap(usize).BitmapError.OutOfBounds, vmm2.copyData(&vmm, true, buff[0..buff.len], vmm.end)); | ||||
|     std.testing.expectError(bitmap.Bitmap(usize).BitmapError.OutOfBounds, vmm.copyData(&vmm2, true, buff[0..buff.len], vmm2.end)); | ||||
|     std.testing.expectEqual(vmm_free_entries, vmm.bmp.num_free_entries); | ||||
|     std.testing.expectEqual(vmm2_free_entries - 1, vmm2.bmp.num_free_entries); | ||||
|     try std.testing.expectError(bitmap.Bitmap(usize).BitmapError.OutOfBounds, vmm2.copyData(&vmm, true, buff[0..buff.len], vmm.end)); | ||||
|     try std.testing.expectError(bitmap.Bitmap(usize).BitmapError.OutOfBounds, vmm.copyData(&vmm2, true, buff[0..buff.len], vmm2.end)); | ||||
|     try std.testing.expectEqual(vmm_free_entries, vmm.bmp.num_free_entries); | ||||
|     try std.testing.expectEqual(vmm2_free_entries - 1, vmm2.bmp.num_free_entries); | ||||
| } | ||||
| 
 | ||||
| test "copyDaya to" { | ||||
|  | @ -851,9 +852,9 @@ test "copyDaya to" { | |||
|     var buff2 = @intToPtr([*]u8, alloc)[0..buff.len]; | ||||
|     try vmm2.copyData(&vmm, false, buff[0..], alloc); | ||||
| 
 | ||||
|     std.testing.expectEqualSlices(u8, buff[0..buff.len], buff2); | ||||
|     std.testing.expectEqual(vmm_free_entries, vmm.bmp.num_free_entries); | ||||
|     std.testing.expectEqual(vmm2_free_entries - 1, vmm2.bmp.num_free_entries); | ||||
|     try std.testing.expectEqualSlices(u8, buff[0..buff.len], buff2); | ||||
|     try std.testing.expectEqual(vmm_free_entries, vmm.bmp.num_free_entries); | ||||
|     try std.testing.expectEqual(vmm2_free_entries - 1, vmm2.bmp.num_free_entries); | ||||
| } | ||||
| 
 | ||||
| var test_allocations: ?*bitmap.Bitmap(u64) = null; | ||||
|  | @ -881,7 +882,6 @@ pub fn testInit(num_entries: u32) Allocator.Error!VirtualMemoryManager(arch.VmmP | |||
|             allocations.clearEntry(entry) catch unreachable; | ||||
|         } | ||||
|     } | ||||
|     var allocations = test_allocations orelse unreachable; | ||||
|     const mem_profile = mem.MemProfile{ | ||||
|         .vaddr_end = undefined, | ||||
|         .vaddr_start = undefined, | ||||
|  | @ -920,11 +920,15 @@ pub fn testDeinit(vmm: *VirtualMemoryManager(arch.VmmPayload)) void { | |||
| ///     IN pstart: usize - The start of the physical region to map | ||||
| ///     IN pend: usize - The end of the physical region to map | ||||
| ///     IN attrs: Attributes - The attributes to map with | ||||
| ///     IN/OUT allocator: *Allocator - The allocator to use. Ignored | ||||
| ///     IN/OUT allocator: Allocator - The allocator to use. Ignored | ||||
| ///     IN payload: arch.VmmPayload - The payload value. Expected to be arch.KERNEL_VMM_PAYLOAD | ||||
| /// | ||||
| fn testMap(vstart: usize, vend: usize, pstart: usize, pend: usize, attrs: Attributes, allocator: *Allocator, payload: arch.VmmPayload) (Allocator.Error || MapperError)!void { | ||||
|     std.testing.expectEqual(arch.KERNEL_VMM_PAYLOAD, payload); | ||||
| fn testMap(vstart: usize, vend: usize, pstart: usize, pend: usize, attrs: Attributes, allocator: Allocator, payload: arch.VmmPayload) MapperError!void { | ||||
|     // Suppress unused var warning | ||||
|     _ = attrs; | ||||
|     _ = allocator; | ||||
|     if (vend - vstart != pend - pstart) return MapperError.AddressMismatch; | ||||
|     std.testing.expectEqual(arch.KERNEL_VMM_PAYLOAD, payload) catch unreachable; | ||||
|     var vaddr = vstart; | ||||
|     var allocations = test_allocations.?; | ||||
|     while (vaddr < vend) : (vaddr += BLOCK_SIZE) { | ||||
|  | @ -940,8 +944,10 @@ fn testMap(vstart: usize, vend: usize, pstart: usize, pend: usize, attrs: Attrib | |||
| ///     IN vend: usize - The end of the virtual region to unmap | ||||
| ///     IN payload: arch.VmmPayload - The payload value. Expected to be arch.KERNEL_VMM_PAYLOAD | ||||
| /// | ||||
| fn testUnmap(vstart: usize, vend: usize, allocator: *Allocator, payload: arch.VmmPayload) MapperError!void { | ||||
|     std.testing.expectEqual(arch.KERNEL_VMM_PAYLOAD, payload); | ||||
| fn testUnmap(vstart: usize, vend: usize, allocator: Allocator, payload: arch.VmmPayload) MapperError!void { | ||||
|     // Suppress unused var warning | ||||
|     _ = allocator; | ||||
|     std.testing.expectEqual(arch.KERNEL_VMM_PAYLOAD, payload) catch unreachable; | ||||
|     var vaddr = vstart; | ||||
|     var allocations = test_allocations.?; | ||||
|     while (vaddr < vend) : (vaddr += BLOCK_SIZE) { | ||||
|  | @ -1093,7 +1099,6 @@ fn rt_copyData(vmm: *VirtualMemoryManager(arch.VmmPayload)) void { | |||
|     } | ||||
|     // Make sure that the data at the allocated address is correct | ||||
|     // Since vmm2 is a mirror of vmm, this address should be mapped by the CPU's MMU | ||||
|     const dest_buff2 = @intToPtr([*]u8, addr2)[0..buff3.len]; | ||||
|     if (!std.mem.eql(u8, buff3[0..buff3.len], dest_buff)) { | ||||
|         panic(@errorReturnTrace(), "Third lot of data copied doesn't have the expected values\n", .{}); | ||||
|     } | ||||
|  |  | |||
|  | @ -1 +0,0 @@ | |||
| insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long_insanely_long.txt | ||||
|  | @ -67,6 +67,8 @@ const types = .{ | |||
|     .{ "fn (usize) bool", "FN_IUSIZE_OBOOL", "", "", "" }, | ||||
|     .{ "fn (RtcRegister) u8", "FN_IRTCREGISTER_OU8", "", "", "" }, | ||||
|     .{ "fn (IdtEntry) bool", "FN_IIDTENTRY_OBOOL", "idt_mock", "", "IdtEntry" }, | ||||
|     .{ "fn (*const GdtPtr) anyerror!void", "FN_IPTRCONSTGDTPTR_EERROR_OVOID", "", "", "" }, | ||||
|     .{ "fn (*const IdtPtr) anyerror!void", "FN_IPTRCONSTIDTPTR_EERROR_OVOID", "", "", "" }, | ||||
|     .{ "fn (*const GdtPtr) void", "FN_IPTRCONSTGDTPTR_OVOID", "", "", "" }, | ||||
|     .{ "fn (*const IdtPtr) void", "FN_IPTRCONSTIDTPTR_OVOID", "", "", "" }, | ||||
| 
 | ||||
|  | @ -74,6 +76,7 @@ const types = .{ | |||
|     .{ "fn (u8, u8) u16", "FN_IU8_IU8_OU16", "", "", "" }, | ||||
|     .{ "fn (u8, fn () callconv(.Naked) void) IdtError!void", "FN_IU8_IFNCCNAKEDOVOID_EIDTERROR_OVOID", "", "", "" }, | ||||
|     .{ "fn (u16, u8) void", "FN_IU16_IU8_OVOID", "", "", "" }, | ||||
|     .{ "fn (u16, u16) anyerror!void", "FN_IU16_IU16_EERROR_OVOID", "", "", "" }, | ||||
|     .{ "fn (u16, u16) void", "FN_IU16_IU16_OVOID", "", "", "" }, | ||||
|     .{ "fn (u16, u32) void", "FN_IU16_IU32_OVOID", "", "", "" }, | ||||
|     .{ "fn (StatusRegister, bool) u8", "FN_ISTATUSREGISTER_IBOOL_OU8", "", "", "" }, | ||||
|  | @ -179,7 +182,7 @@ pub fn main() (Allocator.Error || File.OpenError || File.WriteError || File.Read | |||
| 
 | ||||
|     var gpa = std.heap.GeneralPurposeAllocator(.{}){}; | ||||
|     defer _ = gpa.deinit(); | ||||
|     const allocator = &gpa.allocator; | ||||
|     const allocator = gpa.allocator(); | ||||
| 
 | ||||
|     // All the string | ||||
|     const imports_str = comptime genImports(); | ||||
|  |  | |||
|  | @ -56,12 +56,12 @@ pub const CpuState = struct { | |||
|     user_ss: u32, | ||||
| }; | ||||
| 
 | ||||
| pub const VmmPayload = switch (builtin.arch) { | ||||
| pub const VmmPayload = switch (builtin.cpu.arch) { | ||||
|     .i386 => *x86_paging.Directory, | ||||
|     else => unreachable, | ||||
| }; | ||||
| 
 | ||||
| pub const KERNEL_VMM_PAYLOAD: VmmPayload = switch (builtin.arch) { | ||||
| pub const KERNEL_VMM_PAYLOAD: VmmPayload = switch (builtin.cpu.arch) { | ||||
|     .i386 => &x86_paging.kernel_directory, | ||||
|     else => unreachable, | ||||
| }; | ||||
|  | @ -78,8 +78,21 @@ var KERNEL_VADDR_START: u32 = 0xC0100000; | |||
| var KERNEL_VADDR_END: u32 = 0xC1100000; | ||||
| var KERNEL_ADDR_OFFSET: u32 = 0xC0000000; | ||||
| 
 | ||||
| pub fn map(start: usize, end: usize, p_start: usize, p_end: usize, attrs: vmm.Attributes, allocator: *Allocator, payload: VmmPayload) !void {} | ||||
| pub fn unmap(start: usize, end: usize, allocator: *Allocator, payload: VmmPayload) !void {} | ||||
| pub fn map(start: usize, end: usize, p_start: usize, p_end: usize, attrs: vmm.Attributes, allocator: Allocator, payload: VmmPayload) !void { | ||||
|     _ = start; | ||||
|     _ = end; | ||||
|     _ = p_start; | ||||
|     _ = p_end; | ||||
|     _ = attrs; | ||||
|     _ = allocator; | ||||
|     _ = payload; | ||||
| } | ||||
| pub fn unmap(start: usize, end: usize, allocator: Allocator, payload: VmmPayload) !void { | ||||
|     _ = start; | ||||
|     _ = end; | ||||
|     _ = allocator; | ||||
|     _ = payload; | ||||
| } | ||||
| 
 | ||||
| pub fn out(port: u16, data: anytype) void { | ||||
|     return mock_framework.performAction("out", void, .{ port, data }); | ||||
|  | @ -134,10 +147,14 @@ pub fn haltNoInterrupts() noreturn { | |||
| } | ||||
| 
 | ||||
| pub fn initSerial(boot_payload: BootPayload) Serial { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = boot_payload; | ||||
|     return .{ .write = undefined }; | ||||
| } | ||||
| 
 | ||||
| pub fn initTTY(boot_payload: BootPayload) TTY { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = boot_payload; | ||||
|     return .{ | ||||
|         .print = undefined, | ||||
|         .setCursor = undefined, | ||||
|  | @ -148,6 +165,8 @@ pub fn initTTY(boot_payload: BootPayload) TTY { | |||
| } | ||||
| 
 | ||||
| pub fn initMem(payload: BootPayload) Allocator.Error!mem.MemProfile { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = payload; | ||||
|     return MemProfile{ | ||||
|         .vaddr_end = @ptrCast([*]u8, &KERNEL_VADDR_END), | ||||
|         .vaddr_start = @ptrCast([*]u8, &KERNEL_VADDR_START), | ||||
|  | @ -162,13 +181,22 @@ pub fn initMem(payload: BootPayload) Allocator.Error!mem.MemProfile { | |||
|     }; | ||||
| } | ||||
| 
 | ||||
| pub fn initTask(t: *Task, entry_point: usize, allocator: *Allocator) Allocator.Error!void {} | ||||
| pub fn initTask(t: *Task, entry_point: usize, allocator: Allocator) Allocator.Error!void { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = t; | ||||
|     _ = entry_point; | ||||
|     _ = allocator; | ||||
| } | ||||
| 
 | ||||
| pub fn initKeyboard(allocator: *Allocator) Allocator.Error!?*Keyboard { | ||||
| pub fn initKeyboard(allocator: Allocator) Allocator.Error!?*Keyboard { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = allocator; | ||||
|     return null; | ||||
| } | ||||
| 
 | ||||
| pub fn getDevices(allocator: *Allocator) Allocator.Error![]Device { | ||||
| pub fn getDevices(allocator: Allocator) Allocator.Error![]Device { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = allocator; | ||||
|     return &[_]Device{}; | ||||
| } | ||||
| 
 | ||||
|  | @ -188,6 +216,8 @@ pub fn getDateTime() DateTime { | |||
| } | ||||
| 
 | ||||
| pub fn init(mem_profile: *const MemProfile) void { | ||||
|     // Suppress unused variable warnings | ||||
|     _ = mem_profile; | ||||
|     // I'll get back to this as this doesn't effect the current testing. | ||||
|     // When I come on to the mem.zig testing, I'll fix :) | ||||
|     //return mock_framework.performAction("init", void, mem_profile); | ||||
|  |  | |||
|  | @ -194,7 +194,7 @@ fn Mock() type { | |||
| 
 | ||||
|             // Test that the types match | ||||
|             const expect_type = comptime getDataElementType(expected_function); | ||||
|             expectEqual(expect_type, @as(DataElementType, test_element)); | ||||
|             expectEqual(expect_type, @as(DataElementType, test_element)) catch @panic("Function type is not as expected\n"); | ||||
| 
 | ||||
|             // Types match, so can use the expected type to get the actual data | ||||
|             const actual_function = getDataValue(expected_function, test_element); | ||||
|  | @ -219,13 +219,13 @@ fn Mock() type { | |||
| 
 | ||||
|             // Test that the types match | ||||
|             const expect_type = comptime getDataElementType(ExpectedType); | ||||
|             expectEqual(expect_type, @as(DataElementType, elem)); | ||||
|             expectEqual(expect_type, @as(DataElementType, elem)) catch std.debug.panic("Expected {}, got {}\n", .{ expect_type, @as(DataElementType, elem) }); | ||||
| 
 | ||||
|             // Types match, so can use the expected type to get the actual data | ||||
|             const actual_value = getDataValue(ExpectedType, elem); | ||||
| 
 | ||||
|             // Test the values | ||||
|             expectEqual(expected_value, actual_value); | ||||
|             expectEqual(expected_value, actual_value) catch std.debug.panic("Expected {}, got {}\n", .{ expected_value, actual_value }); | ||||
|         } | ||||
| 
 | ||||
|         /// | ||||
|  | @ -254,7 +254,7 @@ fn Mock() type { | |||
| 
 | ||||
|                 // Test that the data match | ||||
|                 const expect_data = comptime getDataElementType(DataType); | ||||
|                 expectEqual(expect_data, @as(DataElementType, action.data)); | ||||
|                 expectEqual(expect_data, @as(DataElementType, action.data)) catch std.debug.panic("Expected {}, got {}\n", .{ expect_data, action.data }); | ||||
|                 return getDataValue(DataType, action.data); | ||||
|             } else { | ||||
|                 std.debug.panic("No more test values for the return of function: " ++ fun_name ++ "\n", .{}); | ||||
|  | @ -281,7 +281,7 @@ fn Mock() type { | |||
|             // Get the function mapping to add the parameter to. | ||||
|             if (self.named_actions.getEntry(fun_name)) |actions_kv| { | ||||
|                 // Take a reference of the value so the underlying action list will update | ||||
|                 var action_list = &actions_kv.value; | ||||
|                 var action_list = &actions_kv.value_ptr; | ||||
|                 const action = Action{ | ||||
|                     .action = action_type, | ||||
|                     .data = createDataElement(data), | ||||
|  | @ -312,7 +312,7 @@ fn Mock() type { | |||
|         pub fn performAction(self: *Self, comptime fun_name: []const u8, comptime RetType: type, params: anytype) RetType { | ||||
|             if (self.named_actions.getEntry(fun_name)) |kv_actions_list| { | ||||
|                 // Take a reference of the value so the underlying action list will update | ||||
|                 var action_list = &kv_actions_list.value; | ||||
|                 var action_list = &kv_actions_list.value_ptr; | ||||
|                 // Peak the first action to test the action type | ||||
|                 if (action_list.*.first) |action_node| { | ||||
|                     const action = action_node.data; | ||||
|  | @ -331,7 +331,7 @@ fn Mock() type { | |||
| 
 | ||||
|                                 expectTest(param_type, param, test_action.data); | ||||
|                             } | ||||
|                             break :ret expectGetValue(fun_name, action_list, RetType); | ||||
|                             break :ret expectGetValue(fun_name, action_list.*, RetType); | ||||
|                         }, | ||||
|                         ActionType.ConsumeFunctionCall => ret: { | ||||
|                             // Now pop the action as we are going to use it | ||||
|  | @ -383,13 +383,13 @@ fn Mock() type { | |||
|             var it = self.named_actions.iterator(); | ||||
|             while (it.next()) |next| { | ||||
|                 // Take a reference so the underlying action list will be updated. | ||||
|                 var action_list = &next.value; | ||||
|                 var action_list = &next.value_ptr; | ||||
|                 if (action_list.*.popFirst()) |action_node| { | ||||
|                     const action = action_node.data; | ||||
|                     switch (action.action) { | ||||
|                         ActionType.TestValue, ActionType.ConsumeFunctionCall => { | ||||
|                             // These need to be all consumed | ||||
|                             std.debug.panic("Unused testing value: Type: {}, value: {} for function '{s}'\n", .{ action.action, @as(DataElementType, action.data), next.key }); | ||||
|                             std.debug.panic("Unused testing value: Type: {}, value: {} for function '{s}'\n", .{ action.action, @as(DataElementType, action.data), next.key_ptr.* }); | ||||
|                         }, | ||||
|                         ActionType.RepeatFunctionCall => { | ||||
|                             // As this is a repeat action, the function will still be here | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| const std = @import("std"); | ||||
| const expect = std.testing.expect; | ||||
| 
 | ||||
| const arch = @import("arch.zig").internals; | ||||
| const arch = @import("arch_mock.zig"); | ||||
| const mock_framework = @import("mock_framework.zig"); | ||||
| 
 | ||||
| pub const initTest = mock_framework.initTest; | ||||
|  | @ -79,8 +79,8 @@ pub fn orig_entry(uc: u8, c: u8) u16 { | |||
| 
 | ||||
| pub fn mock_updateCursor(x: u16, y: u16) void { | ||||
|     // Here we can do any testing we like with the parameters. e.g. test out of bounds | ||||
|     expect(x < WIDTH); | ||||
|     expect(y < HEIGHT); | ||||
|     expect(x < WIDTH) catch @panic("Cursor x is out of bounds\n"); | ||||
|     expect(y < HEIGHT) catch @panic("Cursor x is out of bounds\n"); | ||||
| } | ||||
| 
 | ||||
| pub fn mock_enableCursor() void {} | ||||
|  |  | |||
|  | @ -99,7 +99,7 @@ pub const RuntimeStep = struct { | |||
|         while (true) { | ||||
|             const msg = self.get_msg() catch return true; | ||||
|             defer self.builder.allocator.free(msg); | ||||
|             std.debug.warn("{s}\n", .{msg}); | ||||
|             std.debug.print("{s}\n", .{msg}); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -117,7 +117,7 @@ pub const RuntimeStep = struct { | |||
|             const msg = self.get_msg() catch return false; | ||||
|             defer self.builder.allocator.free(msg); | ||||
|             // Print the line to see what is going on | ||||
|             std.debug.warn("{s}\n", .{msg}); | ||||
|             std.debug.print("{s}\n", .{msg}); | ||||
|             if (std.mem.indexOf(u8, msg, "FAILURE")) |_| { | ||||
|                 return false; | ||||
|             } else if (std.mem.indexOf(u8, msg, "Kernel panic")) |_| { | ||||
|  | @ -142,8 +142,8 @@ pub const RuntimeStep = struct { | |||
|             const msg = self.get_msg() catch return false; | ||||
|             defer self.builder.allocator.free(msg); | ||||
|             // Print the line to see what is going on | ||||
|             std.debug.warn("{s}\n", .{msg}); | ||||
|             if (std.mem.eql(u8, msg, "[emerg] (panic): Kernel panic: integer overflow")) { | ||||
|             std.debug.print("{s}\n", .{msg}); | ||||
|             if (std.mem.eql(u8, msg, "[err] (panic): Kernel panic: integer overflow")) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  | @ -164,7 +164,7 @@ pub const RuntimeStep = struct { | |||
|             const msg = self.get_msg() catch return false; | ||||
|             defer self.builder.allocator.free(msg); | ||||
| 
 | ||||
|             std.debug.warn("{s}\n", .{msg}); | ||||
|             std.debug.print("{s}\n", .{msg}); | ||||
| 
 | ||||
|             // Make sure `[INFO] Switched` then `[INFO] SUCCESS: Scheduler variables preserved` are logged in this order | ||||
|             if (std.mem.eql(u8, msg, "[info] (scheduler): Switched") and state == 0) { | ||||
|  | @ -206,7 +206,7 @@ pub const RuntimeStep = struct { | |||
|         try self.os_proc.spawn(); | ||||
| 
 | ||||
|         // Start up the read thread | ||||
|         var thread = try Thread.spawn(read_logs, self); | ||||
|         var thread = try Thread.spawn(Thread.SpawnConfig{}, read_logs, .{self}); | ||||
| 
 | ||||
|         // Call the testing function | ||||
|         const res = self.test_func(self); | ||||
|  | @ -215,7 +215,7 @@ pub const RuntimeStep = struct { | |||
|         _ = try self.os_proc.kill(); | ||||
| 
 | ||||
|         // Join the thread | ||||
|         thread.wait(); | ||||
|         thread.join(); | ||||
| 
 | ||||
|         // Free the rest of the queue | ||||
|         while (self.msg_queue.get()) |node| { | ||||
|  | @ -248,7 +248,7 @@ pub const RuntimeStep = struct { | |||
|                     return; | ||||
|                 }, | ||||
|                 else => { | ||||
|                     std.debug.warn("Unexpected error: {}\n", .{e}); | ||||
|                     std.debug.print("Unexpected error: {}\n", .{e}); | ||||
|                     unreachable; | ||||
|                 }, | ||||
|             }; | ||||
|  | @ -299,7 +299,7 @@ pub const RuntimeStep = struct { | |||
|     pub fn create(builder: *Builder, test_mode: TestMode, qemu_args: [][]const u8) *RuntimeStep { | ||||
|         const runtime_step = builder.allocator.create(RuntimeStep) catch unreachable; | ||||
|         runtime_step.* = RuntimeStep{ | ||||
|             .step = Step.init(.Custom, builder.fmt("Runtime {s}", .{@tagName(test_mode)}), builder.allocator, make), | ||||
|             .step = Step.init(.custom, builder.fmt("Runtime {s}", .{@tagName(test_mode)}), builder.allocator, make), | ||||
|             .builder = builder, | ||||
|             .msg_queue = Queue.init(), | ||||
|             .os_proc = undefined, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kyle Aleshire
						Kyle Aleshire