How to switch to a low priviliged mode in Riscv? - riscv

I read the specs, but I still don't understand how to achieve that ?
So can someone show me how can you switch to a low privileged mode in riscv in baremetal applications ?

Assuming you are in machine mode:
You could clear the MPP bits of the mstatus CSR and execute a mret instruction. Then you will end up at the address stored in mepc and you will be in user mode.

Related

LPC1800 with S25FL256SA on SPIFI interface problem

LPC1800 is interfaced with external flash memory S25FL064P1F on SPIFI interface. The code present in external flash memory S25FL064P1F is read and executed properly. To increase memory size we just replaced S25FL064P1F by S25FL256SA1F00 on board and stored same code in it. We are observing that code execution speed has reduced significantly in new flash memory S25FL256SA1F00.
I want to know what need to be done to increase code execution speed from new flash memory S25FL256SA1F00.
Please help me.
Thank you!
The code execution speed from new external flash S25FL256S has improved significantly after increasing SPIFI clock.
There is one more observation regarding LPC1800 communication over SPIFI with old flash S25FL064P and new flash S25FL256S.
a. When LPC1800 communicate with flash S25FL064P, data appears on 4 data lines IO0,IO1,IO2,IO3 which means that communication takes place in quad mode.
b. When LPC1800 communicate with flash S25FL256S, data appears on 2 data lines IO0,IO1 which means that communication does not takes place in quad mode. This is because S25FL256S is default working at dual IO or single IO mode. To get data on IO2 and IO3, quad mode need to be set in flash IC using its configuration register.
The LPC1800 SPIFI is currently working in memory mode and same is confirmed as SPIFI status register bit 'MCINIT' is 1. To send command to S25FL256S to configure quad mode in it I aborted LPC1800 SPIFI memory mode by settting RESET bit in SPIFI status register to 1 and saved command in SPIFI command register. But because of memory mode termination by RESET bit 1, code exexution from flash comes to end and therefore code to save command in SPIFI command register is not executed and quad mode is not set in flash S25FL256S.
I want to know how can I send command to flash after abort memory mode. In which sequence SPIFi registers need to be configured?
Please help.

How does instructions like I/O work in user mode?

I am curious because I am reading this OS book which mentions
"User programs always run in user mode, which permits only a subset of the instructions [...]. Generally, all instructions involving I/O and memory protection are disallowed in user mode.
To obtain services from the OS, a user program must make a system call, which traps into the kernel and invokes the OS."
If I/O is not allowed generally in user mode, but let's say I have a program in C++ or Java which asks for input, or let's say something else like a search bar in any program. Whenever I select the search bar (meaning I will write something) then a TRAP instruction is called to invoke the OS (since the OS runs in kernel) to be able to have access to I/O, that is, the keyboard? I am not sure if I follow correctly or what am I getting wrong.
The I/O is not allowed in user mode, but you use Input for applications in the OS, or even with the OS itself there are keyboard commands. If you can use keyboard commands that means the OS is ready for I/O at any time. Then the original statement about I/O instructions being disallowed in user mode.
I am sorry for my ignorance but I am just a little bit confused with these terms and difference between user and kernel. I know the OS runs in kernel mode, and the applications run in the OS, so in the end the applications do have access to I/O.
Don't application need to have the OS deal with there I/O for them?
Meaning, only the OS has the authority to do those type of things...
Am I wrong?
Toss your book in the garbage or use it to line a cat box.
Your apparent paradox is that you think you have to be in kernel mode to do I/O but your book says:
"User programs always run in user mode, which permits only a subset of the instructions"
The resolution to your paradox is that your book is spouting nonsense.
Use programs do not always run in user mode. They frequently run in kernel mode. One of the basic functions of an operating system is to provide a set of kernel mode system services that provide controlled access to kernel mode.
In other words, your instincts here are better than your confusing book's text.
It is important to understand what "user-mode" and "kernel-mode" mean. A process is mapped to memory regions which are user-priviliged, depending on the memory layout. Kernel-mode is basically routines that are in supervisor priviliged memory regions, which are invoked by your program to do the desired work (I/O).

Why did bootsect move itself to 0x90000 in linux(x86)?

I'm studying the process of x86-system booting
and Here is the booting flow:
BIOS load the bootsect from disk MBR to 0x7c00 memory address
boosect copy itself to 0x90000 memory address and jump to 0x90000.
boosect load setup from disk to 0x90200 memory address.
Get some system peripheral device parameters (video, root disk, keyboard,…,etc.) and jump to 0x90200.
Switch system into protected mode move kernel from 0x10000(64K) to 0x0000
Jump to 0x0000 and execute head.s for kernel boot
My question is that why we need to move bootsect itself to 0x90000 first?
Why can't we just move setup and system?
Thanks.
It was (and still is) a good practice to "shadow copy" your bootloader and jump to it. This practice began early when the typical boot loader was limited to the size of a single segment on an x86 processor and a single read sector from disk. Once interrogating the hardware a boot loader could do more advanced work, like install system files (calls, hooks, TSRs, etc), be taken over by viruses, or initialize protected mode and start performing hardware paging of applications, etc.
The origin of the "behavior" predates Linux, you should find that this behavior was common to x86 bootloaders. Possibly any computer based on the IBM PC.
The code presently in Linux was probably derived from this:
Fx. https://stuff.mit.edu/afs/sipb/user/warlord/C/memtest86/bootsect.s
In which case the choice to relocate to 0x90000 is likely arbitrary, the goal was to move the loader out of the default location into a location of its own choice where it wouldn't be tampered with by programs which might allocate from "low mem" (in effect: as a matter of practice.)
I would like to see a definite reason myself :) pretty sure it's really just a remnant of a time when the x86 platform was a DOS platform, and as the hardware evolved new tricks were employed to remain backward compatible with "unfriendly" lowmem code.
I believe that moving the boot sector out of the way was mostly a matter of convenience - there is no hard technical reason that it could not be done otherwise.
That said, 0x7c00 lies less than 32KiB from the start of the memory. 32KiB is often not enough for the setup stage of the kernel, let alone the kernel itself. 0x90000 is well under the area that is reserved by the PC BIOS, while also leaving enough space for the kernel.
In any case, the process you are referring to has not been used by the Linux kernel for several years. The addresses you mentioned are used by versions of the Linux Boot Protocol before v2.02, which was first used with linux-2.4.0. I think that the kernel itself stopped being directly bootable with linux-2.6.0 or so. The arch/i386/boot/bootsect.S file of that version would output a message to that effect when someone attempted to boot the kernel directly.
These days the kernel is usually loaded by a separate bootloader, which is free to use whatever approach it wishes as long as it complies with the boot protocol. The bootloader may have several stages and may even do kernel-y things, such as switching to protected mode itself.

Is it possible to shutdown linux kernel and resume in Real Mode?

Let's say I'd like to start a small linux distro before my ordinary operating system start.
BIOS load MBR and execute MBR.
MBR locates the active partition which is my linux partition.
Linux start and I perform what I need to do.
Linux shut down and I switch to Real Mode again.
The original partition boot sector is loaded and my ordinary OS start.
AFAIK, step 4 will be the difficult task, restore the state on all devices prior to linux, will INT13h be functional? Do I need to restore the Interrupt Vector Table? To mention a few.
Has this been done in any existing project perhaps?
Linux does not normally support this, particularly since it reinitializes hardware in a way that the BIOS and DOS programs may not expect. However, there is some infrastructure to switch back to real mode in specific cases - particularly, for a reboot (see machine_real_restart in arch/x86/kernel/reboot.c) - and has code to reinitialize hardware for kexec or suspend. I suspect you might be able to do something with a combination of these - but I don't know if the result will truly match what DOS or Windows would expect to see on reboot.
A much easier plan would be to use a chainloading bootloader that can be set to boot in a particular configuration once, like GRUB. You could invoke grub-set-default, then reboot. When GRUB comes up, it would then pass control off to Windows. By then setting the fallback OS to the Linux partition, control would return to Linux on the next boot.
Yet another option may be to use Coreboot, but I'm not sure if this is production-ready for booting windows yet.
i haven't tried this so I don't know if it would work, but here goes:
There is an option in the header of a bzImage format kernel file that specifies the address of real mode code to execute before the protected mode code starts. You could create a minimal bzImage-compliant file which has no actual kernel, but which has real mode code to load your MBR using INT 0x13 to 0x7c00 and jmp into it like the BIOS does.
If you use kexec to load the bzImage using the "-t bzImage-x86 --real-mode" options, it should reset the PE bit in CR0 to drop to realmode (as bdonlan above mentioned) and execute the code pointed to by the bzImage header option.
The bzImage header option is called realmode_swtch and is documented in /usr/src/linux/Documentation/x86/boot.txt , the header format code is in /usr/src/linux/arch/x86/boot/header.S
Have you looked into kexec?

Protected Mode Keyboard Access on x86 Assembly

I'm working on keyboard input for a very basic kernel that I'm developing and I'm completely stuck. I can't seem to find any information online that can show me the information I need to know.
My kernel is running in protected mode right now, so I can't use the real mode keyboard routines without jumping into real mode and back, which I'm trying to avoid. I want to be able to access my keyboard from protected mode. Does anyone know how to do this? The only thing I have found so far is that it involves talking to the controller directly using in/out ports, but beyond that I'm stumped. This is, of course, is not something that comes up very often. Normally, Assembly tutorials assume you're running an operating system underneath.
I'm very new to the x86 assembly, so I'm just looking for some good resources for working with the standard hardware from protected mode. I'm compiling the Assembly source code with NASM and linking it to the C source code compiled with DJGPP. Any suggestions?
The MIT operating systems class has lots of good references. In particular, check out Adam Chapweske's resources on keyboard and mouse programming.
In short, yes, you will be using the raw in/out ports, which requires either running in kernel mode, or having the I/O permission bits (IOPL) set in the EFLAGS register. See this page for more details on I/O permissions.
You work with standard legacy hardware the same way on real and protected modes. In this case, you want to talk with the 8042 at I/O ports 0x60 to 0x6f, which in turn will talk to the controller within the keyboard at the other end of the wire.
A quick Google search found me an interesting resource at http://heim.ifi.uio.no/~stanisls/helppc/8042.html (for the 8042) and http://heim.ifi.uio.no/~stanisls/helppc/keyboard_commands.html (for the keyboard).
In case you are not used to it, you talk with components at I/O ports via the IN (read) and OUT (write) opcodes, which receive the I/O port number (a 16-bit value) and the value to be read or written (either 8, 16, or 32 bits). Note that the size read or written is important! Writing 16 bits to something which is expecting 8 bits (or vice versa) is a recipe for disaster. Get used to these opcodes, since you will be using them a lot (it is the only way to talk to some peripherals, including several essential ones; other peripherals use memory-mapped I/O (MMIO) or bus-mastering DMA).
The 8042 PS/2 Controller looks like the simplest possibility.
The oszur11 OS tutorial contains a working example under https://sourceforge.net/p/oszur11/code/ci/master/tree/Chapter_06_Shell/04_Makepp/arch/i386/arch/devices/i8042.c
Just:
sudo apt-get install build-essential qemu
sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu
git clone git://git.code.sf.net/p/oszur11/code oszur11
cd oszur11/Chapter_06_Shell/04_Makepp
make qemu
Tested on Ubuntu 14.04 AMD64.
My GitHub mirror (upstream inactive): https://github.com/cirosantilli/oszur11-operating-system-examples
Not reproducing it here because the code it too long, will update if I manage to isolate the keyboard part in a minimal example.

Resources