Is CPU only compatible to one kind of instruction set architecture? - instruction-set

I start to explore in the area of computer architecture. There are 2 questions about ISA that confuse me.
As far as I know, there are different kinds of ISA such as ARM, MIPS, 80x86, etc. I wonder whether a CPU can only specifically read one kind of ISA. For example, can a processor read both 80x86 and MIPS.
If a CPU is unique to an ISA, how can I check which ISA my PC processor is using? Can I find it out manually?
Thank you

All the CPU/MCU's I know of support just single instruction set.
There is capability of loading microcode to some of the newer architectures that may allow to change the instruction set behavior to some point bot strongly doubt it you can change the instruction set with it. Instruction set and internal CPU/MCU circuitry are strongly dependent. Making universal CPU with changeable instruction set is possible (for example with FPGA) but would be very slow in comparison to direct DIE encoded CPU. With similar technology of Die the clock speed would be may be just few MHz.
Some architectures like i80x86 supports modes that can switch to different kind of operation (16/32/64 bit,real,protected) but its hard to say it is different instruction set or just subset of the same thing ...(matter of perspective)
detection of instruction set.
This is madness. Yes it is possible to detect which type of instruction set you have via program but all the CPU/MCU's have different pinout, interfaces, architectures and are not interchangeable (even in the same architecture class) so you detecting instruction set is meaningless as you alredy know the architecture you are doing the wiring for ...
Anyway the detection would work like this:
have set of test programs of each supported instruction set/architecture that will set specific memory or IO to predefined state if working properly
have watch dog cycling between all the detections and stop on first valid result.

Yes, each type of CPU is unique to an instruction set. The instruction set for ARM will not work with x86, SPARC, etc. There may be some overlap by coincidence, but programs are not compatible between architectures.
Depending on your operating system, there are commands you can run to see this information. For unix/Linux, uname -a will show you what architecture you're running, as well as dmidecode. For Windows OS's, right-clicking on My Computer and selecting Properties should show you your architecture.
For example (Windows 7):
For Linux (I know, it's a super-old distro!):
$ uname -a
Linux hostname 2.6.35-22-generic #33-Ubuntu SMP Sun Sep 19 20:32:27 UTC 2010 x86_64 GNU/Linux
(In this example, the architecture is x86_64), which is 64-bit Intel or AMD. To tell for sure, you can run dmidecode as I mentioned earlier:
~# dmidecode |grep -i proc
Processor Information
Type: Central Processor
Version: AMD Opteron(tm) Processor 154
Processor Information
Type: Central Processor
Version: AMD Opteron(tm) Processor 154

It can actually read any instruction set if the support is implemented. Most of the CPUs nowadays support two/three instructions set that only slightly differ because of 32-bit/64-bit addressing.
x86 supports 16-bit, 32-bit and 64-bit instructions set, ARM support 32-bit, 64-bit, for both Thumb and Thumb-2, etc. Similarly for MIPS for example.
Original Transmeta I believe was flexible about it and supposed to transcompile any instruction set into internal set and run it natively. However it failed and nowadays there is nothing similar to it.
Anyway, once you run application, it's bound to specific instruction set in its header so it can't change it during the runtime. Well, ARM is exception to that - it's able to switch between full and Thumb versions but they are just different encoding for the same...
For the second part - either in your OS GUI or you can usually read it - in Linux by reading /proc/cpuinfo, on Windows in the environment variable PROCESSOR_ARCHITECTURE.

Related

Comparison between USB and Mini PCIe Interfaces

I'm deciding between the MiniPCIe and USB accelerators for a home Linux CCTV project. The host has both USB3 and a MiniPCIe socket. The host's physical environment will range from an ambient 20C up to a potential 35C (during the summer).
I'm struggling to determine the pros and cons for each. I have gotten this far, although many are guesses:
USB:
Supports Windows and MacOS as well as Linux
Appears to have greater mindshare/use/community support on the Internet
External so can be placed to optimise heat dissipation
Heatsink
Two manual performance modes, highest requires ambient temp of max 25C
Can use up to 4.5W (900mA # 5V)
Mini PCie:
Cheaper (25%)
Lower power consumption (1.4W for 416 fps)
Automatic thermal throttling via driver
Relies on host system for active cooling
Will maintain max operation at 85C
There's probably many I've missed. In particular I can't determine if there's any limitations on throughput/capacity using USB vs PCIe. If there is no difference, then I suspect the USB form factor is the better option, if only for the mindshare, although the power usage/heat generated may be a concern.
To whittle this down to an actual question: in what cases would the Mini PCIe interace be a preferred option to the USB one?
If you are looking for a plug&play solution, then I definitely suggest the USB Accelerator. Overall, as long as you have the system requirements then it'll always works (maybe with some modifications to the standard linux configs like adding your user to the plugdev group, ...). Then the software for the CCTV is all up to you :)
PCIes sometimes need extra works like adding extra kernel arguments and modules to keep the pcie modules happy. If you are looking to launch a huge product where volumes are expected, then it is worth investigating it since it's cheaper and more compact. However, the power usage is a must for consideration as the USB Accelerator could uses up to 900mA, so that could play a factor.
May I know what host are you trying to attach the accelerators to?

Docker and -march native

My application benefits greatly from advanced CPU features that gcc can access when it is run with -march native. Docker can smooth over differences in OS, but how does it handle different CPUs? To build an application that can run on any CPU I would have to build for amd64, losing out on a lot of performance. Is there a good way to distribute Docker images when the application needs to be compiled separately for each CPU architecture?
Docker doesn't handle CPU at all. It is just a composition of kernel namespacing, FS system layering (e.g. UnionFS) and process quoting.
When you run something on a docker container it is just an executable running on your OS, without virtualisation, it has access only to a selected set of kernel objects (e.g. devices) and it is chrooted to a FS hierarchy resulting from overlaying vary FSs (including the one in the docker container).
Hence, Docker doesn't handle the CPU at all, it is completely orthogonal to your problem.
As Peter commented there are essentially two ways to CPU-dispatch:
You load the right dynamic library (but every function call into the library uses a pointer).
You build multiple versions of the same statically-linked binary and run the right one.
The main issue is that sometime ISA extensions are orthogonal and this makes the combinations (i.e. the number of libraries/binaries) grow exponential.
So, considering that you are dealing with the Docker's userbase you can simplify the approach a bit (if combinations are a problem):
Either make some ISA extensions required (if the absence of such would degrade the performance too much). For the optional extensions you can use one of the approaches of a above.
Create only a few baseline containers. E.g. One for the generic amd64, one for amd64-avx, one for amd64-avx2-aesni-tsx and similar. The idea being to create only a few containers that covers all, most and few of your users.
EDIT
As BeeOnRope pointed in the comments, Dockers has a version running on Windows. It uses Hyper-V to run a Linux VM with the Linux version of docker.
As Hyper-V is a native VMM, apart from an extra layer, the same considerations apply.
Similarly, there is a macOS version too. This time it uses an hypervisor framework based on xhyve.

What binary in the Update Ramdisk loads the Kernel during an iOS update?

Above image indicates that the Update Ramdisk loads the kernel during an iOS update. If so which binary (ASR, etc.) in the iOS 10.3.1 Update Ramdisk loads the Kernel?
None of them, that's not how ramdisks work.
For starters, the kernel operates on and with the ramdisk, not the other way round. This is true for any kernel-ramdisk pair I've seen on any platform so far.
Furthermore, binaries from the iOS ramdisks are all userland binaries, which means:
They rely on the dynamic linker (/usr/lib/dyld) and system libraries.
They rely on system calls.
They rely on the availability of a file system.
They run in EL0 ("userland"), the least privileged processor mode.
If any of those wanted to load the kernel, there would be a number of problems with that:
The kernel runs in EL1. If you run in EL0, then you are not privileged to access anything in EL1 and thus cannot put any kernel there.
Linking, libraries and system calls work very differently in EL1:
System libraries are not available in EL1. I suppose they could be made available, but since there can only be one binary executing in EL1 at any given time, that sounds like a huge overkill.
There exists a linker for EL1 in iOS (KXLD), but it is part of the iOS kernel and its designed to link kernel extensions to the kernel. It doesn't operate on userland binaries.
While technically you can generate an exception from EL1 targeting EL1 with the svc instruction, you yourself will be invoked to handle it, which means that until you load the kernel, you are the kernel. Userland binaries are not prepared for that.
That said, I'm not sure what your image is trying to express. My best guess would be that it means that the denoted ramdisk is passed to the kernel. In any case though, iBoot is the one loading and setting up the kernel.

Random memory address

I'm working on a virtual machine under Debian with EGLIBC 2.13 in order to learn memory address.
So I wrote a simple code giving me the address of a test variable, but everytime I exec this script, I'm getting a totally different address.
Here's two screens from 2 distincts executions :
What's causing this ? The fact I'm working on a VM or my GLIBC version ?
I guess it's GLIBC to prevent buffer overflow but I can't find my answer on the web.
And is it totally random ?
First, Glib (from GTK) is not GNU libc (a.k.a. glibc)
Then, you are observing the effect of ASLR (address space layout randomization). Don't try to disable it on a server directly connected to the Internet, it is a valuable security measure.
ASLR is mostly provided by the Linux kernel (e.g. when handing mmap(2) without MAP_FIXED, as most implementations of malloc do, and probably also at execve(2) time for the initial stack). Changing your libc (e.g. to musl-libc) won't disable it.
You could disable system-wide ASLR on a laptop (or on a Linux system running inside some VM) using proc(5): run
echo 0 > /proc/sys/kernel/randomize_va_space
as root. Be careful, by doing that you are decreasing the security of your system.
I don't know what you call totally random, but ASLR is random enough. IIRC, (but I might be wrong) the middle 32 bits of the 64-bits address (assuming a 64 bits Linux system) are quite random, to the point of making result of mmap (hence of malloc using it) practically unpredictable and non-reproducible.
BTW, to see ASLR in practice, try several times (with ASLR enabled) the following command
cat /proc/self/maps
this command displays a textual representation of the address space (in virtual memory) of the process running that cat command. You'll see different outputs when you run it several times !
For debugging memory leaks, use valgrind. With a recent GCC 4.9 or better (or recent Clang/LLVM) compiler, the address sanitizer is also useful, so you could compile with gcc then -Wall -Wextra to get all the warnings even the extra ones, then -g to get debug info, then -fsanitize=address

How to programmatically tell that Linux is in PAE or non-PAE mode?

Need to create a script to check to see if the kernel is in PAE mode or not. Surely, it is not enough to just check if the /proc/cpuinfo flags have this 'pae' setting.
We must know if the PAE mechanism has actually been not only implemented, but activated as well.
Because the PAE kernel is now the new default, and that if you need a non-PAE kernel, one has to make another kernel nowadays.
In other word, how do we tell if a kernel is non-PAE on a CPU having PAE (is one of two possible conditions to test for).
Other is, how to tell if a kernel is PAE on a CPU having no PAE-support.
And there's no way to tell if CONFIG_HIGHMEM or CONFIG_PAE kernel configuration option was used in a typical secured kernel.
Usually, CONFIG_PAE can be discovered in your /boot/config-*, like this:
$ cat /boot/config-$(uname -r) | grep PAE
CONFIG_X86_PAE=y
Do you not have access to the that file?
One way is to read the CR4 register and look at bit 5. It will be 1 for PAE and 0 for no PAE. You can read that register in some code running in the kernel (e.g. a kernel driver). You may be able to write a tiny driver for this purpose. It shouldn't be very complicated.

Resources