Skip to content
Snippets Groups Projects
Commit 99f06dce authored by Florent Gluck's avatar Florent Gluck
Browse files
parents beb44888 d7948ad2
No related branches found
No related tags found
No related merge requests found
......@@ -457,7 +457,7 @@ while (!done) {
## Example of MMIO driver code: write to UART
```{.tiny .c}
// Base UART register
// Base UART register (MMIO)
#define UART_BASE 0x10009000
// Data register
......@@ -491,23 +491,23 @@ The following code reads a sector from the first IDE[^10] disk (on the first bus
// A sector has a size of 512 bytes
#define SECTOR_SIZE 512
// IDE status register (on first bus)
#define STATUS_PORT 0x1F7
// Status register on the primary bus (read-only)
#define STATUS_REG 0x1F7
// IDE base port (on first bus)
#define DATA_PORT 0x1F0
// Command register on the primary bus (write-only)
#define CMD_REG 0x1F7
// IDE control register (on first bus)
#define CONTROL_PORT 0x3F6
// Base data register on primary bus (write-only)
#define DATA_BASE_REG 0x1F0
// Assembly function that writes 8-bits data to address port
extern void outb(uint16_t port, uint8_t data)
// Assembly function that writes 8-bits data to address port (PMIO)
void outb(uint16_t port, uint8_t data)
// Assembly function that reads 8-bits from address port
extern uint8_t inb(uint16 port)
// Assembly function that reads 8-bits from address port (PMIO)
uint8_t inb(uint16 port)
// Assembly function that reads 16-bits from address port
extern uint16_t inb(uint16 port)
// Assembly function that reads 16-bits from address port (PMIO)
uint16_t inw(uint16 port)
```
[^10]:\scriptsize IDE is the grandfather of the SATA protocol
......@@ -519,24 +519,24 @@ extern uint16_t inb(uint16 port)
This function reads a sector in LBA[^11] mode:
```{.tiny .c}
// Read sector n into buffer data (512 bytes and already allocated).
// Read sector n into data (allocated by the caller).
void read_sector(int n, uint8_t *data) {
while ((inb(STATUS_PORT) & 0xC0) != 0x40); // Wait for drive to be ready
while ((inb(STATUS_REG) & 0xC0) != 0x40); // Wait for drive to be ready
// Prepare disk for read or write at specified sector in 28-bit LBA mode
outb(0x1F2, 1); // Set sector count
outb(0x1F3, n & 0xff); // Set bits 00-07 of LBA
outb(0x1F4, (n >> 8) & 0xff); // Set bits 08-15 of LBA
outb(0x1F5, (n >> 16) & 0xff); // Set bits 16-23 of LBA
outb(0x1F6, ((n >> 24) & 0x0f) | 0xe0); // Set bits 24-27 of LBA
// + set LBA mode
outb(STATUS_PORT, 0x20); // Command: read sector with retry
outb(DATA_BASE_REG+2, 1); // Set sector count
outb(DATA_BASE_REG+3, n & 0xff); // Set bits 00-07 of LBA
outb(DATA_BASE_REG+4, (n >> 8) & 0xff); // Set bits 08-15 of LBA
outb(DATA_BASE_REG+5, (n >> 16) & 0xff); // Set bits 16-23 of LBA
outb(DATA_BASE_REG+6, ((n >> 24) & 0x0f) | 0xe0); // Set bits 24-27 of LBA
// + set LBA mode
outb(CMD_REG, 0x20); // Command: read sector with retry
while ((inb(STATUS_PORT) & 0xC0) != 0x40); // Wait for drive to be ready
while ((inb(STATUS_REG) & 0xC0) != 0x40); // Wait for drive to be ready
uint16_t *data = (uint16_t *)src;
for (int i = 0; i < SECTOR_SIZE/2; i++) { // Read the sector,
*data = inw(DATA_PORT); // 16-bits at a time
for (int i = 0; i < SECTOR_SIZE/2; i++) { // Read sector content,
*data = inw(DATA_BASE_REG); // 16-bits at a time
data++;
}
}
......@@ -600,14 +600,18 @@ void read_sector(int n, uint8_t *data) {
::: incremental
- The idea behind paravirtualization is simple: the guest OS sends a service request to the VMM
- Conceptually very similar to a user app requesting a service from the OS
- In a OS, a user app can request a service from the OS
- this mechanism is called a **syscall**
- \textcolor{myblue}{In paravirtualization, guest requests a service from the VMM}
- \textcolor{myblue}{this mechanism is called an \textbf{hypercall}}
- Device paravirtualization is simpler and much easier to implement than emulation, hence we describe it first
\vspace{.2cm}
- The idea behind paravirtualization is very similar:
- \textcolor{myblue}{the guest OS \textbf{requests a service} from the VMM}
- this mechanism is called an **hypercall**
\vspace{.3cm}
- **\textcolor{mygreen}{How to implement paravirtualization?}**
- ![](images/hypercalls_vs_syscalls.png){ width=70% }
:::
......@@ -622,13 +626,6 @@ void read_sector(int n, uint8_t *data) {
- guest OS requests to display something
- guest OS requests to send a network packet
[//]: # ----------------------------------------------------------------
## Hypercalls vs system calls
- Mechanism similar to a system call between an application and an OS:\
\vspace{1cm}
\centering ![](images/hypercalls_vs_syscalls.png){ width=80% }
[//]: # ----------------------------------------------------------------
## Benefits of hypercalls
......@@ -645,10 +642,14 @@ void read_sector(int n, uint8_t *data) {
[//]: # ----------------------------------------------------------------
## Hypercall principle
::: incremental
- How does the guest OS request an hypercall to the VMM?
- An hypercall is simply a **specific `VMexit`** triggered by the guest OS, associated to a function **number**
- Hypercalls arguments (parameters) are stored in an area of **shared memory** between VMM and guest OS
:::
[//]: # ----------------------------------------------------------------
## Hypercalls: PMIO or MMIO?
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment