From a7a099032d9f68d4338b021a6323689feacbc47a Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 28 Dec 2021 22:05:41 +0100 Subject: 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. --- i386/i386/db_interface.c | 58 +++++++++++++++++++++++++++++++----------------- i386/intel/pmap.h | 23 +++++++++++++++++++ 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 #include #include +#include #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 @@ -493,6 +493,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) * -- cgit v1.2.3