phil-opp / blog_os

Writing an OS in Rust

Home Page:http://os.phil-opp.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

QEMU Bug in macOS 14: No "Hello, World" in `post-02` - just a black screen.

nskobelevs opened this issue · comments

Having issue with "Hello, World!" now being displayed in QEMU.
Didn't work with my own code - tried the post-02 branch as a sanity check but it didn't work there either.

OS: MacOS Sonoma 14.0
rustc Version: rustc 1.75.0-nightly (475c71da0 2023-10-11)
QEMU Version: 8.1.1

Video:

Screen.Recording.2023-10-13.at.21.21.53.mp4

post-03 seems to work though:

Screenshot 2023-10-13 at 21 32 51

There seems to be a trend of MacBooks not being able to run post-02.
Lemme see...

Edit: See #1249 (comment)

Thanks for reporting this issue! Are these M1/M2 Macs or older ones?

post-03 seems to work though:

That's surprising.. Both branches are writing to the VGA text buffer at 0xb8000, so I don't really understand how one of them works but the other doesn't...

Are these M1/M2 Macs oder older ones?

These are the newer ones that started releasing in 2020 with Apple's new series of ARM chips ("Apple Silicon")

I just tried to reproduce this issue on an M2 MacBook Air, but the post-02 branch worked as expected for me.

It's unlikely to be an issue specifically with M1 vs M2 given architecture is the same as far as I know.

What was the OS, QEMU & rustc versions on the M2 you used? - perhaps something is different there

Same here - the post-02 branch only outputs a blank screen. I'm with an M1Pro Macbook Pro.

Here are the versions that I'm using:
rustc: rustc 1.75.0-nightly (31bc7e2c4 2023-10-30)
QEMU: 8.1.2
OS: macOS Sonoma Version 14.0 Beta (23A5312d)

The line width is different (160, not 80 as the code in post 3 assumes), and the first line is invisible. If you change the function to

#[no_mangle]
pub extern "C" fn _start() -> ! {
    let vga_buffer = 0xb8000 as *mut u8;

    for (i, &byte) in HELLO.iter().enumerate() {
        unsafe {
            let line_offset: isize = 160 * 2;
            let char_offset_within_line: isize = i as isize * 2;
            let color_offset_within_line: isize = i as isize * 2 + 1;
            let char_offset = char_offset_within_line + line_offset;
            let color_offset = color_offset_within_line + line_offset;


            *vga_buffer.offset(char_offset) = byte;
            *vga_buffer.offset(color_offset) = 0xb;
        }
    }

    loop {}
}

You get the first fully visible line

image

And:

let line_offset: isize = 160 * 24;

gives

image

Looking at the code of post 3 I see that it starts writing from column 23. So yeah, that's the problem. Maybe qemu has an ability to specify different settings for VGA, but it seems that it just doesn't display the 0 line with in the current setup

#1252 is the fix

This seems to be related to an issue on how Qemu works on MacOS. Specifically some bug, only visible in certain versions of Qemu...

Qemu Versions affected (going from comments): 8.1.1 and 8.1.2. Both of these are obtainable from Homebrew. MacPorts seems to be outdated and only hold the 8.0.5 version... could anybody test to see if that one is affected ?

I've got the same problem, just figured out that the first line with "Hello world" is visible in full screen mode.

What was the OS, QEMU & rustc versions on the M2 you used? - perhaps something is different there

I'm also using 8.1.2 installed through homebrew. I just tried it again with the latest rustc nightly (2023-11-20), but I still see the expected output on the post-02 branch. I'm on macOS 13.5.2.

I've got the same problem, just figured out that the first line with "Hello world" is visible in full screen mode.

Interesting! Maybe it's just a window sizing bug then. Are you all on MacOS 14?

What was the OS, QEMU & rustc versions on the M2 you used? - perhaps something is different there

I'm also using 8.1.2 installed through homebrew. I just tried it again with the latest rustc nightly (2023-11-20), but I still see the expected output on the post-02 branch. I'm on macOS 13.5.2.

I've got the same problem, just figured out that the first line with "Hello world" is visible in full screen mode.

Interesting! Maybe it's just a window sizing bug then. Are you all on MacOS 14?

Quite interesting... so this verifies that it is not the os code. It is an issue related to Qemu on MacOS.

commented

macOS Sonoma 14.1.1

Latest stable QEMU build also has the first 20-ish pixels at the top of the output window hidden by the window's title bar:

Screenshot 2023-11-24 at 12 12 57 PM

The line width is different (160, not 80 as the code in post 3 assumes), and the first line is invisible. If you change the function to

#[no_mangle]
pub extern "C" fn _start() -> ! {
    let vga_buffer = 0xb8000 as *mut u8;

    for (i, &byte) in HELLO.iter().enumerate() {
        unsafe {
            let line_offset: isize = 160 * 2;
            let char_offset_within_line: isize = i as isize * 2;
            let color_offset_within_line: isize = i as isize * 2 + 1;
            let char_offset = char_offset_within_line + line_offset;
            let color_offset = color_offset_within_line + line_offset;


            *vga_buffer.offset(char_offset) = byte;
            *vga_buffer.offset(color_offset) = 0xb;
        }
    }

    loop {}
}

You get the first fully visible line

image And:
let line_offset: isize = 160 * 24;

gives

image Looking at the code of `post 3` I see that it starts writing from column `23`. So yeah, that's the problem. Maybe qemu has an ability to specify different settings for VGA, but it seems that it just doesn't display the `0` line with in the current setup

Works for me, thanks!

The line width is different (160, not 80 as the code in post 3 assumes), and the first line is invisible. If you change the function to

#[no_mangle]
pub extern "C" fn _start() -> ! {
    let vga_buffer = 0xb8000 as *mut u8;

    for (i, &byte) in HELLO.iter().enumerate() {
        unsafe {
            let line_offset: isize = 160 * 2;
            let char_offset_within_line: isize = i as isize * 2;
            let color_offset_within_line: isize = i as isize * 2 + 1;
            let char_offset = char_offset_within_line + line_offset;
            let color_offset = color_offset_within_line + line_offset;


            *vga_buffer.offset(char_offset) = byte;
            *vga_buffer.offset(color_offset) = 0xb;
        }
    }

    loop {}
}

You get the first fully visible line
image
And:

let line_offset: isize = 160 * 24;

gives
image
Looking at the code of post 3 I see that it starts writing from column 23. So yeah, that's the problem. Maybe qemu has an ability to specify different settings for VGA, but it seems that it just doesn't display the 0 line with in the current setup

Works for me, thanks!

thanks for the solution

The line width is different (160, not 80 as the code in post 3 assumes), and the first line is invisible. If you change the function to

#[no_mangle]
pub extern "C" fn _start() -> ! {
    let vga_buffer = 0xb8000 as *mut u8;

    for (i, &byte) in HELLO.iter().enumerate() {
        unsafe {
            let line_offset: isize = 160 * 2;
            let char_offset_within_line: isize = i as isize * 2;
            let color_offset_within_line: isize = i as isize * 2 + 1;
            let char_offset = char_offset_within_line + line_offset;
            let color_offset = color_offset_within_line + line_offset;


            *vga_buffer.offset(char_offset) = byte;
            *vga_buffer.offset(color_offset) = 0xb;
        }
    }

    loop {}
}

You get the first fully visible line
image

And:

let line_offset: isize = 160 * 24;

gives
image

Looking at the code of post 3 I see that it starts writing from column 23. So yeah, that's the problem. Maybe qemu has an ability to specify different settings for VGA, but it seems that it just doesn't display the 0 line with in the current setup

Thanks that work for me

I have opened this issue: https://gitlab.com/qemu-project/qemu/-/issues/1994

It's an API difference between Sonoma and earlier macOS versions NSView documented in https://developer.apple.com/documentation/macos-release-notes/appkit-release-notes-for-macos-14.

Sonoma set NSView.clipsToBounds to false by default and it was true in earlier versions.

DrDonk seems to he working on it, it will hopefully be in the upstream Qemu soon...

@AtomicGamer9523 Thanks a lot, that is great news!

To anybody that stumbled upon this via a google search or because of a pinned comment, here's a quick rundown:

  • If you are not on MacOS, this should not affect you
  • If you are not using Qemu, this should not affect you
  • If you are on MacOS version 13 and bellow, this should not affect you

Now, if you are on MacOS newer than than version 14, and you are using Qemu, listen up.
There is a window-sizing bug in Qemu that will shift text up, preventing you from being able to see some of it.
It is fixed in Qemu 9.0. Bellow are package managers and latest version of Qemu available:

Edit: The package managers have updated their packages. Both of them are now up to date. To fix the big, just update Qemu!

Looks like both homebrew and macPorts provide v0.9 now, do I see that right?

Looks like both homebrew and macPorts provide v0.9 now, do I see that right?

Correct, updating my comment.

Edit: Is it safe to close this issue as completed ?

Great! Yes, I think we can close this then. I'll keep it pinned for a while, so it should still be visible enough.