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) { ...@@ -457,7 +457,7 @@ while (!done) {
## Example of MMIO driver code: write to UART ## Example of MMIO driver code: write to UART
```{.tiny .c} ```{.tiny .c}
// Base UART register // Base UART register (MMIO)
#define UART_BASE 0x10009000 #define UART_BASE 0x10009000
// Data register // Data register
...@@ -491,23 +491,23 @@ The following code reads a sector from the first IDE[^10] disk (on the first bus ...@@ -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 // A sector has a size of 512 bytes
#define SECTOR_SIZE 512 #define SECTOR_SIZE 512
// IDE status register (on first bus) // Status register on the primary bus (read-only)
#define STATUS_PORT 0x1F7 #define STATUS_REG 0x1F7
// IDE base port (on first bus) // Command register on the primary bus (write-only)
#define DATA_PORT 0x1F0 #define CMD_REG 0x1F7
// IDE control register (on first bus) // Base data register on primary bus (write-only)
#define CONTROL_PORT 0x3F6 #define DATA_BASE_REG 0x1F0
// Assembly function that writes 8-bits data to address port // Assembly function that writes 8-bits data to address port (PMIO)
extern void outb(uint16_t port, uint8_t data) void outb(uint16_t port, uint8_t data)
// Assembly function that reads 8-bits from address port // Assembly function that reads 8-bits from address port (PMIO)
extern uint8_t inb(uint16 port) uint8_t inb(uint16 port)
// Assembly function that reads 16-bits from address port // Assembly function that reads 16-bits from address port (PMIO)
extern uint16_t inb(uint16 port) uint16_t inw(uint16 port)
``` ```
[^10]:\scriptsize IDE is the grandfather of the SATA protocol [^10]:\scriptsize IDE is the grandfather of the SATA protocol
...@@ -519,24 +519,24 @@ extern uint16_t inb(uint16 port) ...@@ -519,24 +519,24 @@ extern uint16_t inb(uint16 port)
This function reads a sector in LBA[^11] mode: This function reads a sector in LBA[^11] mode:
```{.tiny .c} ```{.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) { 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 // Prepare disk for read or write at specified sector in 28-bit LBA mode
outb(0x1F2, 1); // Set sector count outb(DATA_BASE_REG+2, 1); // Set sector count
outb(0x1F3, n & 0xff); // Set bits 00-07 of LBA outb(DATA_BASE_REG+3, n & 0xff); // Set bits 00-07 of LBA
outb(0x1F4, (n >> 8) & 0xff); // Set bits 08-15 of LBA outb(DATA_BASE_REG+4, (n >> 8) & 0xff); // Set bits 08-15 of LBA
outb(0x1F5, (n >> 16) & 0xff); // Set bits 16-23 of LBA outb(DATA_BASE_REG+5, (n >> 16) & 0xff); // Set bits 16-23 of LBA
outb(0x1F6, ((n >> 24) & 0x0f) | 0xe0); // Set bits 24-27 of LBA outb(DATA_BASE_REG+6, ((n >> 24) & 0x0f) | 0xe0); // Set bits 24-27 of LBA
// + set LBA mode // + set LBA mode
outb(STATUS_PORT, 0x20); // Command: read sector with retry 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; uint16_t *data = (uint16_t *)src;
for (int i = 0; i < SECTOR_SIZE/2; i++) { // Read the sector, for (int i = 0; i < SECTOR_SIZE/2; i++) { // Read sector content,
*data = inw(DATA_PORT); // 16-bits at a time *data = inw(DATA_BASE_REG); // 16-bits at a time
data++; data++;
} }
} }
...@@ -600,14 +600,18 @@ void read_sector(int n, uint8_t *data) { ...@@ -600,14 +600,18 @@ void read_sector(int n, uint8_t *data) {
::: incremental ::: incremental
- The idea behind paravirtualization is simple: the guest OS sends a service request to the VMM - In a OS, a user app can request a service from the OS
- Conceptually very similar to a user app requesting a service from the OS
- this mechanism is called a **syscall** - 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}} \vspace{.2cm}
- Device paravirtualization is simpler and much easier to implement than emulation, hence we describe it first
- 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} \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) { ...@@ -622,13 +626,6 @@ void read_sector(int n, uint8_t *data) {
- guest OS requests to display something - guest OS requests to display something
- guest OS requests to send a network packet - 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 ## Benefits of hypercalls
...@@ -645,10 +642,14 @@ void read_sector(int n, uint8_t *data) { ...@@ -645,10 +642,14 @@ void read_sector(int n, uint8_t *data) {
[//]: # ---------------------------------------------------------------- [//]: # ----------------------------------------------------------------
## Hypercall principle ## Hypercall principle
::: incremental
- How does the guest OS request an hypercall to the VMM? - 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** - 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 arguments (parameters) are stored in an area of **shared memory** between VMM and guest OS
:::
[//]: # ---------------------------------------------------------------- [//]: # ----------------------------------------------------------------
## Hypercalls: PMIO or MMIO? ## 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