track changes

This commit is contained in:
Murphy 2025-04-01 12:32:51 -04:00
parent 4dc44e8fce
commit 9945ad6119
Signed by: freya
GPG key ID: 9FBC6FFD6D2DBF17
5 changed files with 175 additions and 183 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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');
}

View file

@ -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);
}
/*

View file

@ -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);
}