summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2021-12-28 22:05:41 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2021-12-28 22:10:40 +0100
commita7a099032d9f68d4338b021a6323689feacbc47a (patch)
tree87a7ff415a03976cf3a27c8dee535e31ca6e139f
parentabd21321841032248800bca9abc64867f7ba6b59 (diff)
ddb: Fix accessing high memory
User processes loaded in high memory are not visible to ddb through the direct mapping. We can however read/write data through copy_from/to_phys.
-rw-r--r--i386/i386/db_interface.c58
-rw-r--r--i386/intel/pmap.h23
2 files changed, 61 insertions, 20 deletions
diff --git a/i386/i386/db_interface.c b/i386/i386/db_interface.c
index 1a7070e3..7761571d 100644
--- a/i386/i386/db_interface.c
+++ b/i386/i386/db_interface.c
@@ -39,6 +39,7 @@
#include <i386/pmap.h>
#include <i386/proc_reg.h>
#include <i386/locore.h>
+#include <i386at/biosmem.h>
#include "gdt.h"
#include "trap.h"
@@ -442,10 +443,10 @@ kdb_kentry(
boolean_t db_no_vm_fault = TRUE;
int
-db_user_to_kernel_address(
+db_user_to_phys_address(
const task_t task,
vm_offset_t addr,
- vm_offset_t *kaddr,
+ vm_offset_t *paddr,
int flag)
{
pt_entry_t *ptp;
@@ -470,7 +471,29 @@ db_user_to_kernel_address(
}
return(-1);
}
- *kaddr = ptetokv(*ptp) + (addr & (INTEL_PGBYTES-1));
+
+ *paddr = pte_to_pa(*ptp) + (addr & (INTEL_PGBYTES-1));
+ return(0);
+}
+
+int
+db_user_to_kernel_address(
+ const task_t task,
+ vm_offset_t addr,
+ vm_offset_t *kaddr,
+ int flag)
+{
+ vm_offset_t paddr;
+
+ if (db_user_to_phys_address(task, addr, &paddr, flag) < 0)
+ return(-1);
+
+ if (paddr >= biosmem_directmap_end()) {
+ db_printf("\naddr %08x is stored in highmem at physical %016llx, accessing it is not supported yet\n", addr, (unsigned long long) paddr);
+ return(-1);
+ }
+
+ *kaddr = phystokv(paddr);
return(0);
}
@@ -487,7 +510,7 @@ db_read_bytes(
{
char *src;
int n;
- vm_offset_t kern_addr;
+ vm_offset_t phys_addr;
src = (char *)addr;
if ((addr >= VM_MIN_KERNEL_ADDRESS && addr < VM_MAX_KERNEL_ADDRESS) || task == TASK_NULL) {
@@ -504,16 +527,14 @@ db_read_bytes(
return TRUE;
}
while (size > 0) {
- if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
+ if (db_user_to_phys_address(task, addr, &phys_addr, 1) < 0)
return FALSE;
- src = (char *)kern_addr;
n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
if (n > size)
n = size;
size -= n;
addr += n;
- while (--n >= 0)
- *data++ = *src++;
+ copy_from_phys(phys_addr, (vm_offset_t) data, n);
}
return TRUE;
}
@@ -596,21 +617,18 @@ db_write_bytes_user_space(
char *data,
task_t task)
{
- char *dst;
int n;
- vm_offset_t kern_addr;
+ vm_offset_t phys_addr;
while (size > 0) {
- if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
+ if (db_user_to_phys_address(task, addr, &phys_addr, 1) < 0)
return;
- dst = (char *)kern_addr;
n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
if (n > size)
n = size;
size -= n;
addr += n;
- while (--n >= 0)
- *dst++ = *data++;
+ copy_to_phys((vm_offset_t) data, phys_addr, n);
}
}
@@ -621,7 +639,7 @@ db_check_access(
task_t task)
{
int n;
- vm_offset_t kern_addr;
+ vm_offset_t phys_addr;
if (addr >= VM_MIN_KERNEL_ADDRESS) {
if (kernel_task == TASK_NULL)
@@ -633,7 +651,7 @@ db_check_access(
task = current_thread()->task;
}
while (size > 0) {
- if (db_user_to_kernel_address(task, addr, &kern_addr, 0) < 0)
+ if (db_user_to_phys_address(task, addr, &phys_addr, 0) < 0)
return FALSE;
n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
if (n > size)
@@ -651,7 +669,7 @@ db_phys_eq(
const task_t task2,
vm_offset_t addr2)
{
- vm_offset_t kern_addr1, kern_addr2;
+ vm_offset_t phys_addr1, phys_addr2;
if (addr1 >= VM_MIN_KERNEL_ADDRESS || addr2 >= VM_MIN_KERNEL_ADDRESS)
return FALSE;
@@ -662,10 +680,10 @@ db_phys_eq(
return FALSE;
task1 = current_thread()->task;
}
- if (db_user_to_kernel_address(task1, addr1, &kern_addr1, 0) < 0
- || db_user_to_kernel_address(task2, addr2, &kern_addr2, 0) < 0)
+ if (db_user_to_phys_address(task1, addr1, &phys_addr1, 0) < 0
+ || db_user_to_phys_address(task2, addr2, &phys_addr2, 0) < 0)
return FALSE;
- return(kern_addr1 == kern_addr2);
+ return(phys_addr1 == phys_addr2);
}
#define DB_USER_STACK_ADDR (VM_MIN_KERNEL_ADDRESS)
diff --git a/i386/intel/pmap.h b/i386/intel/pmap.h
index 0ca03148..f24b3a71 100644
--- a/i386/intel/pmap.h
+++ b/i386/intel/pmap.h
@@ -494,6 +494,29 @@ extern void pmap_zero_page (phys_addr_t);
extern void pmap_copy_page (phys_addr_t, phys_addr_t);
/*
+ * copy_to_phys(src_addr_v, dst_addr_p, count)
+ *
+ * Copy virtual memory to physical memory
+ */
+extern void
+copy_to_phys(
+ vm_offset_t src_addr_v,
+ phys_addr_t dst_addr_p,
+ int count);
+
+/*
+ * copy_from_phys(src_addr_p, dst_addr_v, count)
+ *
+ * Copy physical memory to virtual memory. The virtual memory
+ * is assumed to be present (e.g. the buffer pool).
+ */
+extern void
+copy_from_phys(
+ phys_addr_t src_addr_p,
+ vm_offset_t dst_addr_v,
+ int count);
+
+/*
* kvtophys(addr)
*
* Convert a kernel virtual address to a physical address