/* * Finish a fork operation, with process p2 nearly set up. * Copy and update the kernel stack and pcb, making the child * ready to run, and marking it so that it can return differently * than the parent. Returns 1 in the child process, 0 in the parent. * We currently double-map the user area so that the stack is at the same * address in each process; in the future we will probably relocate * the frame pointers on the stack after copying. */ void cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize, void (*func)(void *), void *arg) { struct pcb *pcb = &p2->p_addr->u_pcb; struct trapframe *tf; struct switchframe *sf; #if NNPX > 0 npxsave_proc(p1, 1); #endif p2->p_md.md_flags = p1->p_md.md_flags; /* Copy pcb from proc p1 to p2. */ if (p1 == curproc) { /* Sync the PCB before we copy it. */ savectx(curpcb); } #ifdef DIAGNOSTIC else if (p1 != &proc0) panic("cpu_fork: curproc"); #endif *pcb = p1->p_addr->u_pcb; /* * Preset these so that gdt_compact() doesn't get confused if called * during the allocations below. * * Note: pcb_ldt_sel is handled in the pmap_activate() call when * we run the new process. */ p2->p_md.md_tss_sel = GSEL(GNULL_SEL, SEL_KPL); /* Fix up the TSS. */ pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); pcb->pcb_tss.tss_esp0 = (int)p2->p_addr + USPACE - 16; p2->p_md.md_tss_sel = tss_alloc(pcb); /* * Copy the trapframe, and arrange for the child to return directly * through rei(). */ p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1; *tf = *p1->p_md.md_regs; /* * If specified, give the child a different stack. */ if (stack != NULL) tf->tf_esp = (u_int)stack + stacksize; sf = (struct switchframe *)tf - 1; sf->sf_ppl = 0; sf->sf_esi = (int)func; sf->sf_ebx = (int)arg; sf->sf_eip = (int)proc_trampoline; pcb->pcb_esp = (int)sf; }
/* * Set up proc0's TSS and LDT. */ void x86_64_proc0_tss_ldt_init(void) { struct pcb *pcb; int x; gdt_init(); cpu_info_primary.ci_curpcb = pcb = &proc0.p_addr->u_pcb; pcb->pcb_flags = 0; pcb->pcb_tss.tss_iobase = (u_int16_t)((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss); for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++) pcb->pcb_iomap[x] = 0xffffffff; pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL); pcb->pcb_cr0 = rcr0(); pcb->pcb_tss.tss_rsp0 = (u_int64_t)proc0.p_addr + USPACE - 16; pcb->pcb_tss.tss_ist[0] = (u_int64_t)proc0.p_addr + PAGE_SIZE; proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_rsp0 - 1; proc0.p_md.md_tss_sel = tss_alloc(pcb); ltr(proc0.p_md.md_tss_sel); lldt(pcb->pcb_ldt_sel); }
TSPICALL Tspi_DAA_IssueSetup(TSS_HDAA hDAA, // in UINT32 issuerBaseNameLength, // in BYTE* issuerBaseName, // in UINT32 numberPlatformAttributes, // in UINT32 numberIssuerAttributes, // in TSS_HDAA_DATA* keyPair, // out (TSS_KEY_PAIR) TSS_HDAA_DATA* publicKeyProof) // out (TSS_DAA_PK_PROOF) { TSS_RESULT result; KEY_PAIR_WITH_PROOF_internal *key_proof; TSS_DAA_KEY_PAIR *tss_daa_key_pair; TSS_HCONTEXT hContext; #ifdef TSS_DEBUG int before = mallinfo().uordblks; #endif LogDebug( "TSPI_DAA_IssueSetup hDAA=%d ",hDAA); // TODO: lock access to _hContext if ((result = obj_daa_get_tsp_context(hDAA, &hContext))) return result; result = generate_key_pair(numberIssuerAttributes, numberPlatformAttributes, issuerBaseNameLength, issuerBaseName, &key_proof); if (result != TSS_SUCCESS) return result; LogDebug("TSPI_DAA_IssueSetup convert internal structure to public allocated using tspi_alloc"); LogDebug("key_proof->proof->length_challenge=%d key_proof->proof->length_response=%d", key_proof->proof->length_challenge, key_proof->proof->length_response); // prepare out parameters *publicKeyProof = i_2_e_TSS_DAA_PK_PROOF( key_proof->proof, &tss_alloc, hContext); tss_daa_key_pair = (TSS_DAA_KEY_PAIR *)tss_alloc( sizeof(TSS_DAA_KEY_PAIR), hContext); if (tss_daa_key_pair == NULL) { LogError("malloc of %d bytes failed", sizeof(TSS_DAA_KEY_PAIR)); result = TSPERR(TSS_E_OUTOFMEMORY); goto close; } tss_daa_key_pair->private_key = i_2_e_TSS_DAA_PRIVATE_KEY( key_proof->private_key, &tss_alloc, hContext); tss_daa_key_pair->public_key = i_2_e_TSS_DAA_PK( key_proof->pk, &tss_alloc, hContext); *keyPair = (TSS_HKEY)tss_daa_key_pair; close: bi_flush_memory(); LogDebug("TSPI_DAA_IssueSetup ALLOC DELTA:%d", mallinfo().uordblks-before); LogDebug( "TSPI_DAA_IssueSetup end return=%d ",result); return result; }
TSS_RESULT Tspi_DAA_Issuer_GenerateKey(TSS_HDAA_ISSUER_KEY hIssuerKey, // in UINT32 issuerBaseNameLength, // in BYTE* issuerBaseName) // in { TSS_RESULT result; KEY_PAIR_WITH_PROOF_internal *key_proof; TSS_DAA_KEY_PAIR *tss_daa_key_pair; TSS_HCONTEXT tspContext; UINT32 numberPlatformAttributes, numberIssuerAttributes; #ifdef TSS_DEBUG int before = mallinfo().uordblks; #endif if ((result = obj_daaissuerkey_get_tsp_context(hIssuerKey, &tspContext))) return result; if ((result = obj_daaissuerkey_get_attribs(hIssuerKey, &numberIssuerAttributes, &numberPlatformAttributes))) return result; if ((result = generate_key_pair(numberIssuerAttributes, numberPlatformAttributes, issuerBaseNameLength, issuerBaseName, &key_proof))) return result; LogDebugFn("convert internal structure to public allocated using tspi_alloc"); LogDebug("key_proof->proof->length_challenge=%d key_proof->proof->length_response=%d", key_proof->proof->length_challenge, key_proof->proof->length_response); // prepare out parameters *publicKeyProof = i_2_e_TSS_DAA_PK_PROOF( key_proof->proof, &tss_alloc, tspContext); tss_daa_key_pair = (TSS_DAA_KEY_PAIR *)tss_alloc( sizeof(TSS_DAA_KEY_PAIR), tspContext); if (tss_daa_key_pair == NULL) { LogError("malloc of %d bytes failed", sizeof(TSS_DAA_KEY_PAIR)); result = TSPERR(TSS_E_OUTOFMEMORY); goto close; } tss_daa_key_pair->private_key = i_2_e_TSS_DAA_PRIVATE_KEY( key_proof->private_key, &tss_alloc, tspContext); tss_daa_key_pair->public_key = i_2_e_TSS_DAA_PK( key_proof->pk, &tss_alloc, tspContext); *keyPair = (TSS_HKEY)tss_daa_key_pair; close: bi_flush_memory(); LogDebug("TSPI_DAA_IssueSetup ALLOC DELTA:%d", mallinfo().uordblks-before); LogDebug( "TSPI_DAA_IssueSetup end return=%d ",result); return result; }
void x86_64_init_pcb_tss_ldt(struct cpu_info *ci) { int x; struct pcb *pcb = ci->ci_idle_pcb; pcb->pcb_tss.tss_iobase = (u_int16_t)((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss); for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++) pcb->pcb_iomap[x] = 0xffffffff; /* XXXfvdl pmap_kernel not needed */ pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSYSSEL(GLDT_SEL, SEL_KPL); pcb->pcb_cr0 = rcr0(); ci->ci_idle_tss_sel = tss_alloc(pcb); }
/* * Finish a fork operation, with process p2 nearly set up. * Copy and update the kernel stack and pcb, making the child * ready to run, and marking it so that it can return differently * than the parent. Returns 1 in the child process, 0 in the parent. * We currently double-map the user area so that the stack is at the same * address in each process; in the future we will probably relocate * the frame pointers on the stack after copying. */ void cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize, void (*func)(void *), void *arg) { struct pcb *pcb = &p2->p_addr->u_pcb; struct trapframe *tf; struct switchframe *sf; /* * If fpuproc != p1, then the fpu h/w state is irrelevant and the * state had better already be in the pcb. This is true for forks * but not for dumps. * * If fpuproc == p1, then we have to save the fpu h/w state to * p1's pcb so that we can copy it. */ if (p1->p_addr->u_pcb.pcb_fpcpu != NULL) fpusave_proc(p1, 1); p2->p_md.md_flags = p1->p_md.md_flags; syscall_intern(p2); /* Copy pcb from proc p1 to p2. */ if (p1 == curproc) { /* Sync the PCB before we copy it. */ savectx(curpcb); } #ifdef DIAGNOSTIC else if (p1 != &proc0) panic("cpu_fork: curproc"); #endif *pcb = p1->p_addr->u_pcb; /* * Preset these so that gdt_compact() doesn't get confused if called * during the allocations below. * * Note: pcb_ldt_sel is handled in the pmap_activate() call when * we run the new process. */ p2->p_md.md_tss_sel = GSEL(GNULL_SEL, SEL_KPL); /* * Activate the addres space. Note this will refresh pcb_ldt_sel. */ pmap_activate(p2); /* Fix up the TSS. */ pcb->pcb_tss.tss_rsp0 = (u_int64_t)p2->p_addr + USPACE - 16; pcb->pcb_tss.tss_ist[0] = (u_int64_t)p2->p_addr + PAGE_SIZE - 16; p2->p_md.md_tss_sel = tss_alloc(pcb); /* * Copy the trapframe. */ p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_tss.tss_rsp0 - 1; *tf = *p1->p_md.md_regs; setredzone(p2); /* * If specified, give the child a different stack. */ if (stack != NULL) tf->tf_rsp = (u_int64_t)stack + stacksize; sf = (struct switchframe *)tf - 1; sf->sf_ppl = IPL_NONE; sf->sf_r12 = (u_int64_t)func; sf->sf_r13 = (u_int64_t)arg; if (func == child_return) sf->sf_rip = (u_int64_t)child_trampoline; else sf->sf_rip = (u_int64_t)proc_trampoline; pcb->pcb_rsp = (u_int64_t)sf; pcb->pcb_rbp = 0; }