Skip to content
This repository has been archived by the owner. It is now read-only.

Long mode #8

Open
wants to merge 5 commits into
base: master
from

Conversation

Projects
None yet
5 participants
@japaric
Copy link
Contributor

japaric commented Sep 18, 2016

@japaric

This comment has been minimized.

Copy link
Contributor Author

japaric commented Sep 18, 2016

@homunkulus

This comment has been minimized.

Copy link
Collaborator

homunkulus commented Sep 18, 2016

⌛️ Trying commit bcc0c6a with merge bcc0c6a...

@homunkulus

This comment has been minimized.

Copy link
Collaborator

homunkulus commented Sep 18, 2016

💔 Test failed - status-travis

accessed via pure Rust, AFAIK. For that reason, this part is written in inline assembly.
- Caveat: Because we are telling `rustc` to use a 32-bit target, `rustc` always emit 32-bit
instructions and we can't actually use 64-bit instructions/registers in the section of the program
where the CPU is already in long mode. Yikes, I'll have to think about how to solve this.

This comment has been minimized.

@japaric

japaric Sep 18, 2016

Author Contributor

I think this can be solved by splitting this crate in two: one crates that does the booting process and is compiled for a 32-bit target and the other crate that exposes the long_mode_start symbol and is compiled for a 64-bit target. The issue is that I think the compiler won't link together crates compiled for different types (imagine mixing a crate compiled for ARM with a crate compiled for x86). If that's the case we could compiled the boot crate as a staticlib and link that staticlib into the long crate. That should bypass the "same target" check.

All this is speculation from my part. I don't know if it will actually work.

This comment has been minimized.

@steveklabnik

steveklabnik Sep 18, 2016

That sounds about right to me.

update .travis.yml
the target changed
@japaric

This comment has been minimized.

Copy link
Contributor Author

japaric commented Sep 18, 2016

@homunkulus

This comment has been minimized.

Copy link
Collaborator

homunkulus commented Sep 18, 2016

⌛️ Trying commit 2ed58d5 with merge 2ed58d5...

// extra selector
asm!("mov es, ax" :::: "intel");

// FIXME Is this the right syntax for a far jump?

This comment has been minimized.

@japaric

japaric Sep 18, 2016

Author Contributor

Thought on this part?

This comment has been minimized.

@steveklabnik

steveklabnik Sep 18, 2016

I think so? Not 100% sure though.

@homunkulus

This comment has been minimized.

Copy link
Collaborator

homunkulus commented Sep 18, 2016

💔 Test failed - status-travis

travis: don't build in debug mode
it fails to link for some reason :-/
@japaric

This comment has been minimized.

Copy link
Contributor Author

japaric commented Sep 18, 2016

@homunkulus

This comment has been minimized.

Copy link
Collaborator

homunkulus commented Sep 18, 2016

⌛️ Trying commit 137b345 with merge 137b345...

@homunkulus

This comment has been minimized.

Copy link
Collaborator

homunkulus commented Sep 18, 2016

☀️ Test successful - status-travis
State: approved= try=True

accessed via pure Rust, AFAIK. For that reason, this part is written in inline assembly.
- Caveat: Because we are telling `rustc` to use a 32-bit target, `rustc` always emit 32-bit
instructions and we can't actually use 64-bit instructions/registers in the section of the program
where the CPU is already in long mode. Yikes, I'll have to think about how to solve this.

This comment has been minimized.

@steveklabnik

steveklabnik Sep 18, 2016

That sounds about right to me.


// move page table address to cr3
asm!("mov eax, p4_table
mov cr3, eax" :::: "intel");

This comment has been minimized.

@steveklabnik

steveklabnik Sep 18, 2016

https://crates.io/crates/x86 would be neat to use here, but it also only supports 64-bit for now, IIRC.

This comment has been minimized.

@phil-opp

phil-opp Sep 18, 2016

They added support for 32 bit lately, but I'm not sure if it's already on crates.io…

This comment has been minimized.

@Ericson2314

Ericson2314 Sep 23, 2016

0.8 on crates.io has the bulk of this.

// extra selector
asm!("mov es, ax" :::: "intel");

// FIXME Is this the right syntax for a far jump?

This comment has been minimized.

@steveklabnik

steveklabnik Sep 18, 2016

I think so? Not 100% sure though.

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 23, 2016

A thought that I've been rolling around in my head, but haven't tried to implement yet.

What about having a build.rs that builds an asm implementation of the booting into long mode? Treat it like any other dependency. It should basically never change, but even if it does, the rerun-if-changed bit could fix it. Then, the Rust code is all x86-64.

@japaric

This comment has been minimized.

Copy link
Contributor Author

japaric commented Sep 23, 2016

@steveklabnik That would have to shell out to an external assembler like nasm, right? I would prefer if we didn't have to depend on an external tool but, yes, that should work in principle.

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 23, 2016

Yeah, it would still require shelling out. It's not a perfect solution, but
it still lets you get rid of the makefile.

Even worse idea: one huge "inline asm" Rust block? lololol

On Fri, Sep 23, 2016 at 2:48 PM, Jorge Aparicio notifications@github.com
wrote:

@steveklabnik https://github.com/steveklabnik That would have to shell
out to an external assembler like nasm, right? I would prefer if we
didn't have to depend on an external tool but, yes, that should work in
principle.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#8 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AABsih7FQ6mQTGGxofMB73wJn4X8Y5aIks5qtB8BgaJpZM4J_8bw
.

@japaric

This comment has been minimized.

Copy link
Contributor Author

japaric commented Sep 23, 2016

Another approach that could work is have a single x86_64 target, split the boot code into its own crate, compile that boot crate for x86_64 but use -C target-feature to force the use of 32-bit instructions in that crate and, finally, link that crate with the kernel crate which is compiled normally (in 64-bit mode).

I tried this but I couldn't figure a combination of target-features that produces only 32-bit instructions. +32bit-mode,-64bit,-64bit-mode looked promising but it resulted in an LLVM assertion.

@japaric

This comment has been minimized.

Copy link
Contributor Author

japaric commented Sep 23, 2016

Even worse idea: one huge "inline asm" Rust block? lololol

👍. I have actually thought about this! I think it requires global asm instead of inline though (I haven't actually tried)

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 23, 2016

I bet you could configure start? Hm.

On Fri, Sep 23, 2016 at 2:54 PM, Jorge Aparicio notifications@github.com
wrote:

Even worse idea: one huge "inline asm" Rust block? lololol

👍. I have actually thought about this! I think it requires global asm
instead of inline though (I haven't actually tried)


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#8 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AABsij54rb9qbfGotAfAIAfmohOdNX0cks5qtCBhgaJpZM4J_8bw
.

@phil-opp

This comment has been minimized.

Copy link

phil-opp commented Sep 23, 2016

A naked extern function with #[no_mangle] should work. However, I'm not sure if inline assembly supports the bits 32 directive, which we use to generate 32 bit opcodes in nasm...

@Ericson2314

This comment has been minimized.

Copy link

Ericson2314 commented Sep 23, 2016

I'm guessing a similar situation arises when using arm's dynamic endianness to mix ABIs. To me this is proof that the problem is general enough that Cargo should get a proper solution for this.

I do believe baking exact targets into packages is bad, so I guess the solution would be "chameleon targets" that change their definition based on the crate being built? On the other hand two such crates may share the same dependency in which case it is should be configured (flags) + compiled differently, so naive per-crate target shape-shifting won't work.

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 26, 2016

I implemented the "build using nasm in a build script" over here: intermezzOS/kernel#63

That nasty build script can be made much nicer with the gcc crate, but then you have to use a syntax gcc understands, which isn't nasm. and i haven't taken the time to port it over yet.

I still find #8 (comment) very interesting

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 26, 2016

So, I'm giving that idea a try. I got a libboot.a compiled from the rust in this PR, but when trying to make my other code depend on it, I'm getting

= note: /usr/bin/ld: skipping incompatible ./libboot.a when searching for -lboot

So, something must be slightly off. But I think this might work?

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 26, 2016

So, @mkpankov pointed out this:

$ readelf -h libboot.a 

File: libboot.a(boot.0.o)
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32

It's going to know that it's a 32-bit ELF file, and not link it in. Given this,

Another approach that could work is have a single x86_64 target, split the boot code into its own crate, compile that boot crate for x86_64 but use -C target-feature to force the use of 32-bit instructions in that crate and, finally, link that crate with the kernel crate which is compiled normally (in 64-bit mode).

Seems like it's probably the correct approach.

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 26, 2016

Regarding the "can inline asm do BITS 32", I got a tweet that says yes: https://twitter.com/rpjohnst/status/780474494066450433

@japaric

This comment has been minimized.

Copy link
Contributor Author

japaric commented Sep 26, 2016

@steveklabnik did the libboot.a approach work in the end? I tried the two targets, x86 and x86_64, approach and hitted the same problem: the libboot.a (a rust crate compiled as a staticlib) compiled for x86 was a 32-bit elf/library and got ignored by the linker when I tried to link it to the x86_64 kernel crate.

Seems like it's probably the correct approach.

Yeah, but LLVM isn't cooperating :-/.

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 26, 2016

I couldn't get it to work, due to the 64/32 issue.

@steveklabnik

This comment has been minimized.

Copy link

steveklabnik commented Sep 26, 2016

One other idea I had: if we converted into intel syntax rather than nasm-specific, we could just use the gcc crate to build it. rust already uses gcc for the linker, so that would eliminate one more dep...

p4_table[0] = &p3_table[0] as *const _ as usize as u64 | 0b11;
p3_table[0] = &p2_table[0] as *const _ as usize as u64 | 0b11;

for (entry, i) in p2_table.iter_mut().zip(0..) {

This comment has been minimized.

@steveklabnik

steveklabnik Oct 12, 2016

.enumerate() rather than zip(0 ?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.