Porting Chromium to Windows RT

Search This thread

nbetcher

Senior Member
Jan 2, 2010
499
115
38
Phoenix, AZ
No, what's on there is right... Is it possible you're mixing up the Surface RT and Surface 2? I don't think the RT is supposed to have 4.22.500
Yeah, I had them backwards, I do have the Surface 2. I've gotten conflicting information from multiple sources, including Microsoft, and it's been infuriating to say the least. But System Information states it's the Surface 2. So then that's a plus. 😁 Thanks for forcing me to resolve that lingering discrepancy. 😂
 

nbetcher

Senior Member
Jan 2, 2010
499
115
38
Phoenix, AZ
Because it's apparently significantly slower than on other Linux-capable devices because it can't be booted directly from the UEFI, and X11/Xorg was never very performant or known for low-latency 2D graphics on lower-end devices like Windows is. The X11 protocol was designed to be versatile, namely for being capable of communicating over sockets (TCP or otherwise).

Anyway, that aside, Linux's power management isn't historically as good as Window's, namely due to the power management drivers (same for the graphics too actually).

I don't know how many distros use Wayland by default now or if there's even a more performant and efficient driver for it for the Surface RT / 2, or even how good Wayland in general is, but somehow I just don't think it's up to par with Windows despite my lack of experience with all of that.

Perhaps most people wouldn't care about such things, or even that I might be forced to go that route myself eventually, but by doing this project I can learn a lot about the Surfaces and their problems. That may help me in the future.
 
Because it's apparently significantly slower than on other Linux-capable devices because it can't be booted directly from the UEFI, and X11/Xorg was never very performant or known for low-latency 2D graphics on lower-end devices like Windows is. The X11 protocol was designed to be versatile, namely for being capable of communicating over sockets (TCP or otherwise).

Anyway, that aside, Linux's power management isn't historically as good as Window's, namely due to the power management drivers (same for the graphics too actually).

I don't know how many distros use Wayland by default now or if there's even a more performant and efficient driver for it for the Surface RT / 2, or even how good Wayland in general is, but somehow I just don't think it's up to par with Windows despite my lack of experience with all of that.

Perhaps most people wouldn't care about such things, or even that I might be forced to go that route myself eventually, but by doing this project I can learn a lot about the Surfaces and their problems. That may help me in the future.
Thanks. I never knew how well battery life was because I bought mine as a budget raspberry pi🤣
however I do want to thank you for your work and your love to such a device that was trashedand abandoned by Microsoft because it deserves more attention
 

nbetcher

Senior Member
Jan 2, 2010
499
115
38
Phoenix, AZ
So this needs to be documented publicly if I don't finish the work. Chromium is a bit of a challenge at RUNTIME (not necessarily to compile) because, while the compiler (MSVC or Clang) allows you to compile V8, the Javascript engine, into Chromium, it does use a moderate amount of assembly. While that assembly is available for ARM32 (due to the Linux variety), WINDOWS 8 RT DOES NOT SUPPORT ARM ASSEMBLY OUT OF THE BOX. Yes, you read that right: the basic assembly of the Surface is not supported by Windows 8 RT. I honestly never even considered that could be a possibility, but it's true.

Instead, it only allows execution of THUMB-2 assembly, an instruction extension in the ARM processors. This was apparently to unify the variety of processors that could have (future tense) shipped with the Surface. Not all hope is lost though, "all" that needs to be done is PatcherGuard bypassed and the kernel executable patched to allow it. There's apparently a decision point in the kernel execution of assembly where it ignores ARM and only allows a return from THUMB-2. It's easily patched, but I haven't done something like that before, and I don't think you can simply patch the kernel executable directly: you have to use a loader to load in the changes (which is why PatcherGuard can be a problem) at runtime.


Here's a copy and paste of what I (and jeybee at the beginning) said in the "Open RT" Discord:


(Some of this is out of context, yes, but it doesn't matter... the intent was preserved in each message)

jeybee: devs-might be worth having a read through this http://mamaich-eng.blogspot.com/
jeybee: specifically "No ARM code on Windows on ARM. Period.
Though MS called their new OS "Windows on ARM" (sometimes Windows on Snapdragon, Windows on Tegra and now Windows RT) - you can't see ARM code in it. Everything is THUMB2.
I don't know the reason of such a limitation - but that caused me several days of debugging while I was working on a DosBox dynamic core WinRT port last year. The dynamic code generated by DosBox is ARM, even the original THUMB generator was using small ARM thunks. Original DosBox works fine on ARM Linux, but on Windows RT it behaves differently. The generated code executes once, twice, but on the 100500 time - it crashes.
The reason was simple. If you read the ARM developer's manual, you'll see that OS should determine the previous mode (ARM or THUMB) on kernel mode entrance (via SWI, interrupt, ...). Seems that MS decided to simplify the handler's code - and assume that the user's code is always THUMB. And they always set the T bit on return to the user land.
So if you are running generated ARM code in your program - you may be forced to the THUMB mode any moment by an interrupt or a task switch."
Phorin: "this leaves one thing to be desired: executing ARM code. I already know how we can patch the kernel so that ARM code can execute without the CPU being switched back to Thumb2 all the time." (https://forum.xda-developers.com/t/bypassing-patchguard.2488560/)
Phorin: "it's currently impossible to execute ARM code reliably on Windows RT is a major reason that Firefox hasn't been ported. Fixing that would require patching two context-switch routines in ntoskrnl.exe." (https://forum.xda-developers.com/t/bypassing-patchguard.2488560/#post-46610744)
Phorin: And, narrowing it down specifically:
"Specifically, KeContextFromKframes in the Windows NT kernel (ntoskrnl.exe) is setting the T bit when freezing a thread's state for a task switch.
This annoyed us jailbreakers for RT/WinPhone, because we couldn't directly port Chrome's JITter without breaking Microsoft's PatchGuard."
I'm assuming that in Test Mode PatchGuard is irrelevant -- I'd be shocked if that wasn't the case. If it is irrelevant, then we have the solution: patch KeContextFromKframes in ntoskrnl.exe to return the mode it was requested to be called from user space.
Phorin: (https://stackoverflow.com/a/33427234)
Phorin: Yes, one of those links above talks about it as well as this https://github.com/Mattiwatti/EfiGuard
Phorin: But that link is for x64 😦
Phorin: Disabling PatchGuard on ARM: https://github.com/tandasat/meow haven't tried it yet though
Phorin: If Win10 truly does run ARM assembly (not THUMB2), that would be helpful to know. Then I could just reference the Win10's kernel for the context switching back to user space
Phorin: So then we just need to disable PatchGuard (seemingly trivial) and patch ntoskrnl.exe with the context-switching behavior from Win10's ntoskrnl.exe. Normally I'd say that would be trivial, but my understanding is that you can't physically patch the ntoskrnl.exe file itself but instead need some kind of loader to patch it in-memory... Something to which is not really in my wheelhouse of expertise.
Phorin: But sure as hell of a lot easier than trying to port all of that ARM assembly to THUMB
Phorin: Plus it would solve a whole host of issues pertaining to other apps
Phorin: I think the only reason someone didn't do this before is because the trust zone-level jailbreak wasn't out. All of this I've come up with isn't really my idea, but it sounds like no one went back to the beginning after the jailbreak came out

One thing to clarify: I'm not even sure that PatcherGuard is running/enforced in test mode (jailbroken), so consider that much of what is shown above could be irrelavent.

For those of you considering just porting the V8 engine's (referenced as, "JIT" -- Just-In-Time [compiler]) from ARM to THUMB-2 is easy: even if it is, which requires a very, very specific, and experienced skillset, consider that future changes to Chromium may not merge cleanly on Git checkout (merge conflicts).

Also, by fixing the kernel running ARM assembly directly, you open the door for other developers to more easily port their apps to Windows 8 RT (or even users recompiling existing ones with the Linux ARM-32 assembly copied to the Win32-equivalent directories).
 

Top Liked Posts

  • There are no posts matching your filters.
  • 19
    So, I've been at this for about 48 hours now (not continuously, but closer than you might think) and I figured I should take a break from modifying project files and puzzling over alignment issues to discuss the project, share some of the problems I've been having and ask if anybody can help, and so on.

    The general idea is "Chromium build for Windows (on x86/x64) and build on ARM (for Linux), so there must be a way to build it for Windows on ARM". For the most part, that even looks like it's true. Probably at least 80% of 654 Visual Studio projects (no, that's not a joke) either build just fine with only minor amounts of work, or are things that we don't actually need (I'll try building the test suites... once everything else builds!!)

    Areas that have given me problems (caution: some chance of brief rants ahead):
    1. v8. Less than you might think, though. Setting the flags for Arm seems to have been enough.
    2. Sandbox. There's a fair bit of thunking coded in assembly going on in the sandbox for x86. Not sure what's up with it (I don't know exactly how the Chromium sandbox works) but it'll have to come out or be replaced. The Linux (including ARM) sandbox seems to be SELinux-based, which doesn't help at all.
    3. Native Client (NaCl). I think all the assembly is in test code, though, so I may just boldly #ifdef if all away.
    4. libjpg-turbo (libjpg). Piles of carefully optimized assembly... for x86 and x64. There is a set of ARM assembly (for Linux) that Visual Studio won't compile, but something else might... or I may tweak until it works. Of course, I could also just accept the speed hit and use the version of libjpg implemented in nice, portable C.
    5. Anything where the developers tried to use some SSE to speed things up. I may be able to replace it with NEON code, or I may just remove it and hope **** doesn't break. We'll see.
    6. Inline assembly in general. Even when it's ARM assembly, Visual Studio / CL.exe don't want anything to do with it (__asm is apparently now an invalid keyword). I suspect I'll have to just pull the assembly out into stand-alone functions in their own files, then compile them to object files and link them back in later. If I can figure out the best way to do this (for example, I'll want to inline the asm functions) then it shouldn't impact performance. Seriously though, I kind of hate inline assembly. I can read assembly just fine, but I'm usually staring at it in a debugger or disassembly tool, not in the middle of source code I'm trying to build...
    7. Everywhere that the current state of the CPU is cared about (exception and crash handlers, in particular) because the CONTEXT structure is, of course, CPU-specific. They're pretty easy to get past, though.
    8. Low-level functions, like MemoryBarrier. Fortunately, it's implemented in ntdll.h... but as a macro, which breaks at least half the places it's referenced. Solution: where it breaks things, undefine the macro and just have it be an inline function that does what the macro did.
    9. Running out of memory. Not even joking... well, OK, a little bit. I've got 32GB; I won't actually run out. Both Visual Studio and cl.exe do at times, though!. Task Manager says VS is currently using 1,928 MB, and before I restarted it, it broke 2.5GB private working set. Pretty good for a program that for some reason is still 32-bit...
    10. Goddamn compiler flags. Seriously, every single project (I mentioned there are over 600, right?) has its LIBPATHs hardcoded to point at x86. Several projects have /D:_X86_ or similar (that's supposed to be set by the build tools, not the user, you idiots...) which plays merry hell with the #ifdef guards. Everything has /SAFESEH specified, not in the actual property table where the IDE could have removed it (unneeded and invlaid on ARM) but in the "extra stuff we'll pass on the build command line" field, which means every single .EXE/.DLL project must be modified or the linker will fail.

    My current biggest goal is the JPG library; nobody wants to use a browser without it. After that, I'll tackle the sandbox, leaving NaCl for last... well, last before whatever else crops up.

    Anyhow, thoughts/comments/advice are welcome... in the mean time, I'm going to go eat something (for the first time in ~22 hours) and then get some sleep.
    4
    Speed isn't the only reason to use a browser. I actually prefer IE myself, but there are some things that other browsers do better than it (in the case of Chrome, parts of HTML5, the syncing across Google services, etc.) Also, Chrome gets updated far more often than IE; IE9 was equal with Chrome on speed at its release, and was far behind by the time IE10 came out.

    The reason for this project, though, is a mixture of interest in what it takes, and a desire to benefit the community. Microsoft has deeped that only software which they have blessed may run on the Windows RT desktop. I disagree, and have chosen (among several other things) to port a web browser because I feel that it's important for users to have choice.
    3
    Working on it! I've gotten over half of the projects to build and link, but some other stuff is adamantly refusing to work. I'm beginning to suspect I'll need to work from the other direction - rather than starting at the bottom and building all the dependencies, then combining them into browser components, and then eventually combining all the components into a complete piece of software, I may have to work from the top, removing components until the whole thing builds (at which point it will likely be useless, or all-but) and then seeing what I can add back in. I thought it would be faster to just assume everything can be made to work and only exclude something if it proved intractable, but at this point I've got a ton of very small components and almost no ability to combine them.

    It would also help if VS was better at managing such truly immense tasks. For example, I have no simple graph of what all is and is not building, so I'm being forced to manually map that onto the VS dependency tree and see what is blocking a given component from building successfully, and how much is dependent upon it, one erroring project at a time (and there are a *lot* of erroring projects - my last attempt to build any substantial part of the system saw 50 of 400 projects fail).
    2
    Bear in mind that the entire thing is 650 projects. If 50 fail at that level, many of the higher-level ones (dependent upon the lower-level) will fail too. I'll see what I can do. I may or may not be able to get v8 actually working (without it, the JS speed will be very bad, think IE8 at best) and I may have to fall back to the legacy libjpeg (which will cut JPEG render speeds by at least a factor of 2). Skia (2D drawing library used by Chrome) has a bunch of assembly optimizations that I need to get it to use the Arm version of instead. There's a couple of total hacks with the library files I've had to pull, which may or may not result in a working final build. We'll see.

    the v8 engine ( used in nodejs ) has been ported to ARM :

    I still can't link : htt p://ww w.it-wars.com/article305/compiler-node-js-pour-arm-v5

    perhaps it will help you

    Edit : oups, I just see that another great user of this forum made the port of nodejs to RT
    2
    Yep... but they did it without v8. That's not an encouraging result, but I feel like I'm so close...