mirror of
https://github.com/kenshineto/kern.git
synced 2025-04-07 11:21:06 +00:00
track changes
This commit is contained in:
parent
4dc44e8fce
commit
9945ad6119
5 changed files with 175 additions and 183 deletions
|
@ -3,8 +3,6 @@
|
|||
**
|
||||
** GENERATED AUTOMATICALLY - DO NOT EDIT
|
||||
**
|
||||
** Creation date: Mon Mar 31 11:38:04 2025
|
||||
**
|
||||
** This header file contains C Preprocessor macros which expand
|
||||
** into the byte offsets needed to reach fields within structs
|
||||
** used in the baseline system. Should those struct declarations
|
||||
|
|
|
@ -163,7 +163,7 @@ static void kreport(bool_t dtrace)
|
|||
}
|
||||
#endif /* TRACE > 0 */
|
||||
|
||||
cio_puts("\n-------------------------------\n");
|
||||
cio_putchar('\n');
|
||||
}
|
||||
|
||||
#if defined(CONSOLE_STATS)
|
||||
|
@ -304,10 +304,10 @@ int main(void)
|
|||
user_init(); // user code handling
|
||||
|
||||
cio_puts("\nModule initialization complete.\n");
|
||||
cio_puts("-------------------------------\n");
|
||||
|
||||
// report our configuration options
|
||||
kreport(true);
|
||||
cio_puts("-------------------------------\n");
|
||||
|
||||
delay(DELAY_2_SEC);
|
||||
|
||||
|
@ -378,21 +378,23 @@ int main(void)
|
|||
|
||||
sio_enable(SIO_RX);
|
||||
|
||||
#if 0
|
||||
// produce a "system state" report
|
||||
cio_puts("System status: Queues ");
|
||||
pcb_queue_dump("R", ready, true);
|
||||
pcb_queue_dump("W", waiting, true);
|
||||
pcb_queue_dump("S", sleeping, true);
|
||||
pcb_queue_dump("Z", zombie, true);
|
||||
pcb_queue_dump("I", sioread, true);
|
||||
cio_puts( "System status: Queues " );
|
||||
pcb_queue_dump( "R", ready, true );
|
||||
pcb_queue_dump( "W", waiting, true );
|
||||
pcb_queue_dump( "S", sleeping, true );
|
||||
pcb_queue_dump( "Z", zombie, true );
|
||||
pcb_queue_dump( "I", sioread, true );
|
||||
ptable_dump_counts();
|
||||
pcb_dump("Current: ", current, true);
|
||||
pcb_dump( "Current: ", current, true );
|
||||
|
||||
delay(DELAY_3_SEC);
|
||||
delay( DELAY_3_SEC );
|
||||
|
||||
vm_print(current->pdir, true, TwoLevel);
|
||||
vm_print( current->pdir, true, TwoLevel );
|
||||
|
||||
delay(DELAY_3_SEC);
|
||||
delay( DELAY_3_SEC );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -963,16 +963,8 @@ void pcb_dump(const char *msg, register pcb_t *pcb, bool_t all)
|
|||
return;
|
||||
}
|
||||
|
||||
cio_printf(" %d", pcb->pid);
|
||||
|
||||
cio_printf(" %s", pcb->state >= N_STATES ? "???" : state_str[pcb->state]);
|
||||
#if 0
|
||||
if( pcb->state >= N_STATES ) {
|
||||
cio_puts( " ????" );
|
||||
} else {
|
||||
cio_printf( " %s", state_str[pcb->state] );
|
||||
}
|
||||
#endif
|
||||
cio_printf(" %d %s", pcb->pid,
|
||||
pcb->state >= N_STATES ? "???" : state_str[pcb->state]);
|
||||
|
||||
if (!all) {
|
||||
// just printing IDs and states on one line
|
||||
|
@ -982,13 +974,6 @@ void pcb_dump(const char *msg, register pcb_t *pcb, bool_t all)
|
|||
// now, the rest of the contents
|
||||
cio_printf(" %s",
|
||||
pcb->priority >= N_PRIOS ? "???" : prio_str[pcb->priority]);
|
||||
#if 0
|
||||
if( pcb->priority >= N_PRIOS ) {
|
||||
cio_puts( " ???" );
|
||||
} else {
|
||||
cio_printf( " %s", prio_str[pcb->priority] );
|
||||
}
|
||||
#endif
|
||||
|
||||
cio_printf(" ticks %u xit %d wake %08x\n", pcb->ticks, pcb->exit_status,
|
||||
pcb->wakeup);
|
||||
|
@ -1007,8 +992,6 @@ void pcb_dump(const char *msg, register pcb_t *pcb, bool_t all)
|
|||
/**
|
||||
** pcb_queue_dump(msg,queue,contents)
|
||||
**
|
||||
** Dump the contents of the specified queue to the console
|
||||
**
|
||||
** @param msg[in] Optional message to print
|
||||
** @param queue[in] The queue to dump
|
||||
** @param contents[in] Also dump (some) contents?
|
||||
|
@ -1124,16 +1107,10 @@ void ptable_dump_counts(void)
|
|||
|
||||
cio_printf("Ptable: %u ***", unknown);
|
||||
for (n = 0; n < N_STATES; ++n) {
|
||||
cio_printf(" %u %s", nstate[n],
|
||||
state_str[n] != NULL ? state_str[n] : "???");
|
||||
#if 0
|
||||
cio_printf( " %u ", nstate[n] );
|
||||
if( state_str[n][0] != '\0' ) {
|
||||
cio_puts( state_str[n] );
|
||||
} else {
|
||||
cio_puts( "???" );
|
||||
if (nstate[n]) {
|
||||
cio_printf(" %u %s", nstate[n],
|
||||
state_str[n] != NULL ? state_str[n] : "???");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
cio_putchar('\n');
|
||||
}
|
||||
|
|
150
kernel/user.c
150
kernel/user.c
|
@ -510,45 +510,72 @@ static context_t *stack_setup(pcb_t *pcb, uint32_t entry, const char **args,
|
|||
** Stack alignment rules for the SysV ABI i386 supplement dictate that
|
||||
** the 'argc' parameter must be at an address that is a multiple of 16;
|
||||
** see below for more information.
|
||||
**
|
||||
** Ultimately, this is what the bottom end of the stack will look like:
|
||||
**
|
||||
** kvavptr
|
||||
** kvacptr |
|
||||
** | |
|
||||
** v v
|
||||
** argc argv av[0] av[1] etc NULL str0 str1 etc.
|
||||
** [....][....][....][....] ... [0000] ... [......0......0.........]
|
||||
** | ^ | | ^ ^
|
||||
** | | | | | |
|
||||
** ------ | ---------------------|-------
|
||||
** ---------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
** Find the user stack. The PDE entry for user address space points
|
||||
** to a page table for the first 4MB of the address space, but the
|
||||
** "pointer" there a physical frame address.
|
||||
** We need to find the last page of the user stack. Find the page
|
||||
** table for the 4MB user address space. The physical address of its
|
||||
** frame is in the first page directory entry. Extract that from the
|
||||
** entry and convert it into a virtual address for the kernel to use.
|
||||
*/
|
||||
pde_t *kv_userpt = (pde_t *)P2V(PTE_ADDR(pcb->pdir[USER_PDE]));
|
||||
assert(kv_userpt != NULL);
|
||||
|
||||
/*
|
||||
** The final entries in that PMT are for the pages of the user stack.
|
||||
** Grab the address of the frame for the last one. (Again, we need
|
||||
** to convert it to a virtual address we can use.)
|
||||
** Grab the physical address of the frame for the last one. (Again,
|
||||
** we need to convert it to a virtual address we can use.)
|
||||
*/
|
||||
|
||||
// the PMT entry for that page
|
||||
pte_t pmt_entry = kv_userpt[USER_STK_LAST_PTE];
|
||||
assert(IS_PRESENT(pmt_entry));
|
||||
|
||||
// kernel VA for the first byte following that page
|
||||
uint8_t *kv_ptr = (uint8_t *)P2V(PTE_ADDR(pmt_entry) + SZ_PAGE);
|
||||
assert(kv_ptr != NULL);
|
||||
// user VA for the first byte of that page
|
||||
uint32_t *uvptr = (uint32_t *)USER_STACK_P2;
|
||||
|
||||
// user VA for the first byte following that page
|
||||
uint32_t *uv_ptr = (uint32_t *)(USER_STACK_P2 + SZ_PAGE);
|
||||
|
||||
// Pointers to where the arg strings should be filled in.
|
||||
uint32_t kv_strings = ((uint32_t)kv_ptr) - argbytes;
|
||||
uint32_t uv_strings = ((uint32_t)uv_ptr) - argbytes;
|
||||
|
||||
// back the pointers up to the nearest word boundary; because we're
|
||||
// moving toward location 0, the nearest word boundary is just the
|
||||
// next smaller address whose low-order two bits are zeroes
|
||||
kv_strings &= MOD4_MASK;
|
||||
uv_strings &= MOD4_MASK;
|
||||
// convert that address to a kernel VA
|
||||
uint32_t *kvptr = (uint32_t *)vm_uva2kva(pcb->pdir, (void *)uvptr);
|
||||
|
||||
/*
|
||||
** Next, we need to copy over the data. Start by determining where
|
||||
** Move these pointers to where the string area will begin. We
|
||||
** will then back up to the next lower multiple-of-four address.
|
||||
*/
|
||||
|
||||
uint32_t uvstrptr = ((uint32_t)uvptr) + SZ_PAGE - argbytes;
|
||||
uvstrptr &= MOD4_MASK;
|
||||
|
||||
uint32_t kvstrptr = ((uint32_t)kvptr) + SZ_PAGE - argbytes;
|
||||
kvstrptr &= MOD4_MASK;
|
||||
|
||||
// Copy over the argv strings, remembering where each string begins
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
// copy the string using kernel addresses
|
||||
strcpy((char *)kvstrptr, kv_args[i]);
|
||||
|
||||
// remember the user address where this string went
|
||||
uv_argv[i] = (char *)uvstrptr;
|
||||
|
||||
// adjust both string addresses
|
||||
kvstrptr += strlengths[i];
|
||||
uvstrptr += strlengths[i];
|
||||
}
|
||||
|
||||
/*
|
||||
** Next, we need to copy over the other data. Start by determining
|
||||
** where 'argc' should go.
|
||||
**
|
||||
** Stack alignment is controlled by the SysV ABI i386 supplement,
|
||||
|
@ -564,68 +591,37 @@ static context_t *stack_setup(pcb_t *pcb, uint32_t entry, const char **args,
|
|||
** Isn't technical documentation fun? Ultimately, this means that
|
||||
** the first parameter to main() should be on the stack at an address
|
||||
** that is a multiple of 16. In our case, that is 'argc'.
|
||||
**
|
||||
*/
|
||||
|
||||
/*
|
||||
** The space needed for argc, argv, and the argv array itself is
|
||||
** argc + 3 words (argc+1 for the argv entries, plus one word each
|
||||
** for argc and argv). We back up that much from 'strings'.
|
||||
** for argc and argv). We back up that much from the string area.
|
||||
*/
|
||||
|
||||
int nwords = argc + 3;
|
||||
uint32_t *kv_acptr = ((uint32_t *)kv_strings) - nwords;
|
||||
uint32_t *uv_acptr = ((uint32_t *)uv_strings) - nwords;
|
||||
uint32_t *kvacptr = ((uint32_t *)kvstrptr) - nwords;
|
||||
uint32_t *uvacptr = ((uint32_t *)uvstrptr) - nwords;
|
||||
|
||||
// back these up to multiple-of-16 addresses for stack alignment
|
||||
kv_acptr = (uint32_t *)(((uint32_t)kv_acptr) & MOD16_MASK);
|
||||
uv_acptr = (uint32_t *)(((uint32_t)uv_acptr) & MOD16_MASK);
|
||||
|
||||
// the argv location
|
||||
uint32_t *kv_avptr = kv_acptr + 1;
|
||||
|
||||
// the user address for the first argv entry
|
||||
uint32_t *uv_avptr = uv_acptr + 2;
|
||||
|
||||
// Copy over the argv strings.
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
// copy the string using kernel addresses
|
||||
strcpy((char *)kv_strings, kv_args[i]);
|
||||
|
||||
// remember the user address where this string went
|
||||
uv_argv[i] = (char *)uv_strings;
|
||||
|
||||
// adjust both string addresses
|
||||
kv_strings += strlengths[i];
|
||||
uv_strings += strlengths[i];
|
||||
}
|
||||
|
||||
/*
|
||||
** Next, we copy in argc, argv, and the pointers. The stack will
|
||||
** look something like this:
|
||||
**
|
||||
** kv_avptr
|
||||
** kv_acptr |
|
||||
** | |
|
||||
** v v
|
||||
** argc argv av[0] av[1] etc NULL str0 str1 etc.
|
||||
** [....][....][....][....] ... [0000] ... [......0......0.........]
|
||||
** | ^ | | ^ ^
|
||||
** | | | | | |
|
||||
** ------ | ---------------------|-------
|
||||
** ---------------------------
|
||||
*/
|
||||
kvacptr = (uint32_t *)(((uint32_t)kvacptr) & MOD16_MASK);
|
||||
uvacptr = (uint32_t *)(((uint32_t)uvacptr) & MOD16_MASK);
|
||||
|
||||
// copy in 'argc'
|
||||
*kv_acptr = argc;
|
||||
*kvacptr = argc;
|
||||
|
||||
// copy in 'argv'
|
||||
*kv_avptr++ = (uint32_t)uv_avptr;
|
||||
// 'argv' immediately follows 'argc', and 'argv[0]' immediately
|
||||
// follows 'argv'
|
||||
uint32_t *kvavptr = kvacptr + 2;
|
||||
*(kvavptr - 1) = (uint32_t)kvavptr;
|
||||
|
||||
// now, the argv entries themselves
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
*kv_avptr++ = (uint32_t)uv_argv[i];
|
||||
*kvavptr++ = (uint32_t)uv_argv[i];
|
||||
}
|
||||
|
||||
// and the trailing NULL
|
||||
*kv_avptr = NULL;
|
||||
*kvavptr = NULL;
|
||||
|
||||
/*
|
||||
** Almost done!
|
||||
|
@ -641,8 +637,8 @@ static context_t *stack_setup(pcb_t *pcb, uint32_t entry, const char **args,
|
|||
|
||||
// Locate the context save area on the stack by backup up one
|
||||
// "context" from where the argc value is saved
|
||||
context_t *kv_ctx = ((context_t *)kv_acptr) - 1;
|
||||
uint32_t uv_ctx = (uint32_t)(((context_t *)uv_acptr) - 1);
|
||||
context_t *kvctx = ((context_t *)kvacptr) - 1;
|
||||
uint32_t uvctx = (uint32_t)(((context_t *)uvacptr) - 1);
|
||||
|
||||
/*
|
||||
** We cleared the entire stack earlier, so all the context
|
||||
|
@ -655,18 +651,18 @@ static context_t *stack_setup(pcb_t *pcb, uint32_t entry, const char **args,
|
|||
** where it winds up.
|
||||
*/
|
||||
|
||||
kv_ctx->eflags = DEFAULT_EFLAGS; // IF enabled, IOPL 0
|
||||
kv_ctx->eip = entry; // initial EIP
|
||||
kv_ctx->cs = GDT_CODE; // segment registers
|
||||
kv_ctx->ss = GDT_STACK;
|
||||
kv_ctx->ds = kv_ctx->es = kv_ctx->fs = kv_ctx->gs = GDT_DATA;
|
||||
kvctx->eflags = DEFAULT_EFLAGS; // IF enabled, IOPL 0
|
||||
kvctx->eip = entry; // initial EIP
|
||||
kvctx->cs = GDT_CODE; // segment registers
|
||||
kvctx->ss = GDT_STACK;
|
||||
kvctx->ds = kvctx->es = kvctx->fs = kvctx->gs = GDT_DATA;
|
||||
|
||||
/*
|
||||
** Return the new context pointer to the caller. It will be our
|
||||
** caller's responsibility to schedule this process.
|
||||
** Return the new context pointer to the caller as a user
|
||||
** space virtual address.
|
||||
*/
|
||||
|
||||
return ((context_t *)uv_ctx);
|
||||
return ((context_t *)uvctx);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
147
kernel/vm.c
147
kernel/vm.c
|
@ -95,13 +95,19 @@ static uint32_t ptcount(pte_t *ptr, bool_t dir)
|
|||
}
|
||||
|
||||
// decode a PDE
|
||||
static void pde_prt(uint32_t level, uint32_t i, uint32_t entry)
|
||||
static void pde_prt(uint32_t level, uint32_t i, uint32_t entry, bool_t all)
|
||||
{
|
||||
if (!IS_PRESENT(entry) && !all) {
|
||||
return;
|
||||
}
|
||||
|
||||
// indent
|
||||
for (int n = 0; n <= level; ++n)
|
||||
cio_puts(" ");
|
||||
|
||||
// line header
|
||||
cio_printf("[%08x] %08x", i, entry);
|
||||
cio_printf("[%03x] %08x", i, entry);
|
||||
|
||||
// perms
|
||||
if (IS_LARGE(entry)) { // PS is 1
|
||||
if ((entry & PDE_PAT) != 0)
|
||||
|
@ -122,43 +128,49 @@ static void pde_prt(uint32_t level, uint32_t i, uint32_t entry)
|
|||
cio_puts(" U");
|
||||
if ((entry & PDE_RW) != 0)
|
||||
cio_puts(" W");
|
||||
cio_puts((entry & PDE_P) != 0 ? " P" : "!P");
|
||||
|
||||
cio_printf(" --> %s %08x", IS_LARGE(entry) ? "Pg" : "PT", PDE_ADDR(entry));
|
||||
// frame address
|
||||
cio_printf(" P --> %s %08x\n", IS_LARGE(entry) ? "Pg" : "PT",
|
||||
PDE_ADDR(entry));
|
||||
}
|
||||
|
||||
// decode a PTE
|
||||
static void pte_prt(uint32_t level, uint32_t i, uint32_t entry)
|
||||
static void pte_prt(uint32_t level, uint32_t i, uint32_t entry, bool_t all)
|
||||
{
|
||||
if (!IS_PRESENT(entry) && !all) {
|
||||
return;
|
||||
}
|
||||
|
||||
// indent
|
||||
for (int n = 0; n <= level; ++n)
|
||||
cio_puts(" ");
|
||||
// line header
|
||||
cio_printf("[%08x] %08x", i, entry);
|
||||
// perms
|
||||
if ((entry & PDE_G) != 0)
|
||||
cio_puts(" G");
|
||||
if ((entry & PDE_PAT) != 0)
|
||||
cio_puts(" PAT");
|
||||
if ((entry & PDE_D) != 0)
|
||||
cio_puts(" D");
|
||||
if ((entry & PDE_A) != 0)
|
||||
cio_puts(" A");
|
||||
if ((entry & PDE_PCD) != 0)
|
||||
cio_puts(" CD");
|
||||
if ((entry & PDE_PWT) != 0)
|
||||
cio_puts(" WT");
|
||||
if ((entry & PDE_US) != 0)
|
||||
cio_puts(" U");
|
||||
if ((entry & PDE_RW) != 0)
|
||||
cio_puts(" W");
|
||||
cio_puts((entry & PDE_P) != 0 ? " P" : "!P");
|
||||
|
||||
cio_printf(" --> Pg %08x", PTE_ADDR(entry));
|
||||
// line header
|
||||
cio_printf("[%03x] %08x", i, entry);
|
||||
|
||||
// perms
|
||||
if ((entry & PTE_G) != 0)
|
||||
cio_puts(" G");
|
||||
if ((entry & PTE_PAT) != 0)
|
||||
cio_puts(" PAT");
|
||||
if ((entry & PTE_D) != 0)
|
||||
cio_puts(" D");
|
||||
if ((entry & PTE_A) != 0)
|
||||
cio_puts(" A");
|
||||
if ((entry & PTE_PCD) != 0)
|
||||
cio_puts(" CD");
|
||||
if ((entry & PTE_PWT) != 0)
|
||||
cio_puts(" WT");
|
||||
if ((entry & PTE_US) != 0)
|
||||
cio_puts(" U");
|
||||
if ((entry & PTE_RW) != 0)
|
||||
cio_puts(" W");
|
||||
|
||||
cio_printf(" P --> Pg %08x\n", PTE_ADDR(entry));
|
||||
}
|
||||
|
||||
/**
|
||||
** Name: pdump
|
||||
** Name: ptdump
|
||||
**
|
||||
** Recursive helper for table hierarchy dump.
|
||||
**
|
||||
|
@ -168,40 +180,44 @@ static void pte_prt(uint32_t level, uint32_t i, uint32_t entry)
|
|||
** @param mode How to display the entries
|
||||
*/
|
||||
ATTR_UNUSED
|
||||
static void pdump(uint_t level, void *pt, bool_t dir, enum vmmode_e mode)
|
||||
static void ptdump(uint_t level, void *pt, bool_t dir, enum vmmode_e mode)
|
||||
{
|
||||
pte_t *ptr = (pte_t *)pt;
|
||||
|
||||
cio_printf("? at 0x%08x:", dir ? "PDir" : "PTbl", (uint32_t)pt);
|
||||
// indent two spaces per level
|
||||
for (int n = 0; n < level; ++n)
|
||||
cio_puts(" ");
|
||||
|
||||
cio_printf("%s at 0x%08x:", dir ? "PDir" : "PTbl", (uint32_t)pt);
|
||||
uint32_t nums = ptcount(ptr, dir);
|
||||
if (dir) {
|
||||
cio_printf(" %u 4MB", (nums >> 16));
|
||||
cio_printf(" 4MB=%u", (nums >> 16));
|
||||
}
|
||||
cio_printf(" %u P %u !P\n", nums & 0xffff,
|
||||
cio_printf(" P=%u !P=%u\n", nums & 0xffff,
|
||||
N_PTE - ((nums >> 16) + (nums & 0xffff)));
|
||||
|
||||
for (uint32_t i = 0; i < (uint32_t)N_PTE; ++i) {
|
||||
pte_t entry = *ptr;
|
||||
if (dir) {
|
||||
// this is a PDIR entry; could be either a 4MB
|
||||
// page, or a PMT pointer
|
||||
if (mode > Simple) {
|
||||
pde_prt(level, i, entry);
|
||||
cio_putchar('\n');
|
||||
if (!IS_LARGE(entry)) {
|
||||
pdump(level + 1, (void *)*ptr, false, mode);
|
||||
pte_t entry = *ptr++;
|
||||
|
||||
// only process this entry if it's not empty
|
||||
if (entry) {
|
||||
if (dir) {
|
||||
// this is a PDIR entry; could be either a 4MB
|
||||
// page, or a PMT pointer
|
||||
if (mode > Simple) {
|
||||
pde_prt(level, i, entry, false);
|
||||
if (!IS_LARGE(entry) && mode > OneLevel) {
|
||||
ptdump(level + 1, (void *)P2V(PTE_ADDR(entry)), false,
|
||||
mode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// just a PMT entry
|
||||
if (mode > Simple) {
|
||||
pte_prt(level, i, entry, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// just a PMT entry
|
||||
if (mode > Simple) {
|
||||
pte_prt(level, i, entry);
|
||||
cio_putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// move to the next entry
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,7 +301,7 @@ void vm_init(void)
|
|||
|
||||
// add the entries for the user address space
|
||||
for (uint32_t addr = 0; addr < NUM_4MB; addr += SZ_PAGE) {
|
||||
int stat = vm_map(kpdir, (void *)addr, addr, SZ_PAGE, PTE_RW);
|
||||
int stat = vm_map(kpdir, (void *)addr, addr, SZ_PAGE, PTE_US | PTE_RW);
|
||||
if (stat != SUCCESS) {
|
||||
cio_printf("vm_init, map %08x->%08x failed, status %d\n", addr,
|
||||
addr, stat);
|
||||
|
@ -315,8 +331,8 @@ void vm_init(void)
|
|||
**
|
||||
** Convert a user VA into a kernel address. Works for all addresses -
|
||||
** if the address is a page address, the low-order nine bits will be
|
||||
** zeroes; otherwise, they is the offset into the page, which is
|
||||
** unchanged within the address spaces.
|
||||
** zeroes; otherwise, they are the offset into the page, which is
|
||||
** unchanged between the address spaces.
|
||||
**
|
||||
** @param pdir Pointer to the page directory to examine
|
||||
** @param va Virtual address to check
|
||||
|
@ -333,7 +349,7 @@ void *vm_uva2kva(pde_t *pdir, void *va)
|
|||
pte_t entry = *pte;
|
||||
|
||||
// is this a valid address for the user?
|
||||
if (IS_PRESENT(entry)) {
|
||||
if (!IS_PRESENT(entry)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -477,7 +493,7 @@ pte_t *vm_getpte(pde_t *pdir, const void *va, bool_t alloc)
|
|||
// NOTE: the allocator is serving us virtual page addresses,
|
||||
// so we must convert them to physical addresses for the
|
||||
// table entries
|
||||
*pde_ptr = V2P(ptbl) | PDE_P | PDE_RW;
|
||||
*pde_ptr = V2P(ptbl) | PDE_P | PDE_RW | PDE_US;
|
||||
}
|
||||
|
||||
// finally, return a pointer to the entry in the page table for this VA
|
||||
|
@ -630,7 +646,7 @@ int vm_add(pde_t *pdir, bool_t wr, bool_t sys, void *va, uint32_t size,
|
|||
if (wr) {
|
||||
entrybase |= PTE_RW;
|
||||
}
|
||||
if (sys) {
|
||||
if (!sys) {
|
||||
entrybase |= PTE_US;
|
||||
}
|
||||
|
||||
|
@ -664,7 +680,7 @@ int vm_add(pde_t *pdir, bool_t wr, bool_t sys, void *va, uint32_t size,
|
|||
memclr(page, SZ_PAGE);
|
||||
|
||||
// create the PTE for this frame
|
||||
uint32_t entry = (uint32_t)(PTE_ADDR(V2P(page)) | entrybase);
|
||||
uint32_t entry = (uint32_t)(V2P(PTE_ADDR(page)) | entrybase);
|
||||
*pte = entry;
|
||||
|
||||
// copy data if we need to
|
||||
|
@ -711,6 +727,7 @@ void vm_free(pde_t *pdir)
|
|||
pde_t *curr = pdir;
|
||||
int nf = 0;
|
||||
int nt = 0;
|
||||
|
||||
for (int i = 0; i < N_PDE; ++i) {
|
||||
// the entry itself
|
||||
pde_t entry = *curr;
|
||||
|
@ -721,14 +738,15 @@ void vm_free(pde_t *pdir)
|
|||
assert(!IS_LARGE(entry));
|
||||
|
||||
// get the PMT pointer
|
||||
pte_t *pmt = (pte_t *)PTE_ADDR(entry);
|
||||
pte_t *pmt = (pte_t *)P2V(PTE_ADDR(entry));
|
||||
|
||||
// walk the PMT
|
||||
for (int j = 0; j < N_PTE; ++j) {
|
||||
pte_t tmp = *pmt;
|
||||
// does this entry point to a frame?
|
||||
if (IS_PRESENT(*pmt)) {
|
||||
if (IS_PRESENT(tmp)) {
|
||||
// yes - free the frame
|
||||
km_page_free((void *)PTE_ADDR(*pmt));
|
||||
km_page_free((void *)P2V(PTE_ADDR(tmp)));
|
||||
++nf;
|
||||
// mark it so we don't get surprised
|
||||
*pmt = 0;
|
||||
|
@ -737,7 +755,7 @@ void vm_free(pde_t *pdir)
|
|||
++pmt;
|
||||
}
|
||||
// now, free the PMT itself
|
||||
km_page_free((void *)PDE_ADDR(entry));
|
||||
km_page_free((void *)P2V(PDE_ADDR(entry)));
|
||||
++nt;
|
||||
*curr = 0;
|
||||
}
|
||||
|
@ -875,7 +893,8 @@ int vm_uvmdup(pde_t *new, pde_t *old)
|
|||
|
||||
if (!IS_LARGE(entry)) {
|
||||
// it's a 4KB page, so we need to duplicate the PMT
|
||||
pte_t *newpt = (pte_t *)vm_pagedup((void *)PTE_ADDR(entry));
|
||||
pte_t *newpt =
|
||||
(pte_t *)vm_pagedup((void *)P2V(PTE_ADDR(entry)));
|
||||
if (newpt == NULL) {
|
||||
return E_NO_MEMORY;
|
||||
}
|
||||
|
@ -883,7 +902,7 @@ int vm_uvmdup(pde_t *new, pde_t *old)
|
|||
uint32_t perms = PERMS(entry);
|
||||
|
||||
// create the new PDE entry by replacing the frame #
|
||||
entry = ((uint32_t)newpt) | perms;
|
||||
entry = ((uint32_t)V2P(PTE_ADDR(newpt))) | perms;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -919,8 +938,8 @@ void vm_print(void *pt, bool_t dir, enum vmmode_e mode)
|
|||
return;
|
||||
}
|
||||
|
||||
cio_printf("Starting at 0x%08x (%s):\n", (uint32_t)pt,
|
||||
cio_printf(", starting at 0x%08x (%s):\n", (uint32_t)pt,
|
||||
dir ? "PDIR" : "PMT");
|
||||
|
||||
pdump(0, pt, dir, mode);
|
||||
ptdump(1, pt, dir, mode);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue