Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for PAE (#97) #599

Merged
merged 1 commit into from
Jan 14, 2022
Merged

Add support for PAE (#97) #599

merged 1 commit into from
Jan 14, 2022

Conversation

pwmarcz
Copy link
Contributor

@pwmarcz pwmarcz commented Jan 13, 2022

Physical memory is still limited to 32-bit addresses, but systems that enable PAE should work now.

Ubuntu 12

I managed to boot the Ubuntu 12 ISO. However, it takes a lot of time to start and is too slow to do anything...

ubuntu12c

(During the boot, it complains about soft lockup - CPU #0 stuck for 23s!. Apparently it happens during the inintrd decompression unlzma, because it's pretty slow. However, if you just wait, it should go through).

Serenity OS (#299)

PAE also should unlock Serenity OS. I tried it, but there are still some issues. After applying some workarounds, I managed to boot it and it looks like it initializes network, mouse, and starts various processes. However, graphics fail to display. I'll post an update later.

let page_table_idx = (addr as u32 >> 12) & 0x1FF;
let page_table_addr = page_table.wrapping_add(page_table_idx << 1);
let page_table_entry = read_aligned32(page_table_addr);
return (page_table_addr as i32, page_table_entry);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where the 64-bit address is read from, is that correct?

Could you change it to something like:

        let page_table_entry = read_aligned64(page_table_addr);
        dbg_assert!(page_table_entry & 0xFFFF_FFFF_0000_0000 == 0, "Unsupported: Physical 64-bit address");
        return (page_table_addr as i32, page_table_entry as i32);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

There's no read_aligned64 and I wasn't sure what the convention for the argument should be. I went with "byte address >> 2", for consistency with read_aligned32 (using "byte address >> 3" sounded like a more confusing option).

The highest bit of PDE and PTE (but not the highest entry, PDPTE) is execute-disable and can be set. I added comments about it.

@copy
Copy link
Owner

copy commented Jan 13, 2022

Brilliant work, thanks. Only change I'd suggest is to assert when a 64-bit address is encountered, so we don't silently cut them off in debug mode.

By the way, I got an older version of SerenityOS working (September 2020). Will add to the website once this is merged.

Screenshot_2022-01-13_12-21-47

Newer versions seem to fail with an issue similar to #597.

Physical memory is still limited to 32-bit addresses, but systems that
enable PAE should work now.
@pwmarcz
Copy link
Contributor Author

pwmarcz commented Jan 13, 2022

Nice! I haven't done anything with Serenity OS yet, but I started working on PAE because I hoped to run it here.

@copy copy merged commit f72d0a9 into copy:master Jan 14, 2022
@copy
Copy link
Owner

copy commented Jan 14, 2022

Thanks!

@copy
Copy link
Owner

copy commented Jan 14, 2022

@pwmarcz Out of curiosity, what workaround were you referring to?

PAE also should unlock Serenity OS. I tried it, but there are still some issues. After applying some workarounds, I managed to boot it and it looks like it initializes network, mouse, and starts various processes.

@pwmarcz
Copy link
Contributor Author

pwmarcz commented Jan 15, 2022

@copy Here's what happened:

  • I couldn't figure out how to boot from the QEMU image, but the extlinux one worked
  • Serenity crashed (kernel panic on serial console) when initializing a pseudo-filesystem and adding information about ACPI; it's a null pointer exception since the ACPI subsystem failed to initialize. I commented out that part:
--- a/Kernel/Firmware/ACPI/Parser.cpp
+++ b/Kernel/Firmware/ACPI/Parser.cpp
@@ -69,6 +69,9 @@ UNMAP_AFTER_INIT ACPISysFSComponent::ACPISysFSComponent(NonnullOwnPtr<KString> t
 
 UNMAP_AFTER_INIT void ACPISysFSDirectory::find_tables_and_register_them_as_components()
 {
+    if (!ACPI::Parser::the())
+        return;
+
     NonnullRefPtrVector<SysFSComponent> components;
     size_t ssdt_count = 0;
     ACPI::Parser::the()->enumerate_static_tables([&](StringView signature, PhysicalAddress p_table, size_t length) {
  • Then, apparently it did not like the fact that the emulated machine only has primary IDE channel, and got stuck trying to initialize the secondary IDE channel (IDEChannel: reset failed, busy flag on master stuck). When the secondary IDE device is absent, the port that Serenity looks at (IDE control) is treated by v86 as unmapped and hardcoded to return 0xFF.

    Unfortunately enabling the secondary IDE channel (i.e. adding a cdrom device, or an "empty" device) didn't work, I think extlinux failed to boot.

    The following workaround (in v86) worked for me:

--- a/src/cpu.js
+++ b/src/cpu.js
@@ -847,6 +847,8 @@ CPU.prototype.init = function(settings, device_bus)
         if(settings.cdrom)
         {
             this.devices.cdrom = new IDEDevice(this, settings.cdrom, undefined, true, ide_device_count++, device_bus);
+        } else {
+            this.io.register_read(0x0376, null, () => 0);
         }
 
         this.devices.pit = new PIT(this, device_bus);
  • After that, Serenity still did not like v86's hard disk. I noticed that it tries to access it through addresses reported by PCI, and when you disable that and use the "standard" addresses, it works.
--- a/Kernel/Storage/ATA/IDEController.cpp
+++ b/Kernel/Storage/ATA/IDEController.cpp
@@ -133,9 +133,9 @@ UNMAP_AFTER_INIT void IDEController::initialize(bool force_pio)
     if (!is_bus_master_capable())
         force_pio = true;
 
-    auto bar0 = PCI::get_BAR0(pci_address());
+    auto bar0 = 0; //PCI::get_BAR0(pci_address());
     auto primary_base_io = (bar0 == 0x1 || bar0 == 0) ? IOAddress(0x1F0) : IOAddress(bar0 & (~1));
-    auto bar1 = PCI::get_BAR1(pci_address());
+    auto bar1 = 0; //PCI::get_BAR1(pci_address());
     auto primary_control_io = (bar1 == 0x1 || bar1 == 0) ? IOAddress(0x3F6) : IOAddress(bar1 & (~1));
     auto bar2 = PCI::get_BAR2(pci_address());
     auto secondary_base_io = (bar2 == 0x1 || bar2 == 0) ? IOAddress(0x170) : IOAddress(bar2 & (~1));
  • At this point, I have an apparently working installation (according to serial logs), except for graphics - nothing appears on screen and the mode doesn't change.

I don't know anything about IDE or PCI, so it's hard for me to say if the above is the fault of v86 or Serenity.

@copy copy mentioned this pull request Jan 18, 2022
@copy copy mentioned this pull request Feb 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants