Re: [PATCH] cpu_number: Short circuit if smp init not done
Damien Zammit, le sam. 04 févr. 2023 03:30:45 +, a ecrit: > This depends on serialised AP init patch. > > Fixes warnings spewing at boot with APIC and SMP > --- > i386/i386/cpu_number.c | 8 > 1 file changed, 8 insertions(+) > > diff --git a/i386/i386/cpu_number.c b/i386/i386/cpu_number.c > index ad4c4b01..eca95d7a 100644 > --- a/i386/i386/cpu_number.c > +++ b/i386/i386/cpu_number.c > @@ -21,10 +21,16 @@ > #include > #include > > +extern int bspdone; Please avoid introducing more such in-C extern declarations. We want them in headers. Samuel
[PATCH] cpu_number: Short circuit if smp init not done
This depends on serialised AP init patch. Fixes warnings spewing at boot with APIC and SMP --- i386/i386/cpu_number.c | 8 1 file changed, 8 insertions(+) diff --git a/i386/i386/cpu_number.c b/i386/i386/cpu_number.c index ad4c4b01..eca95d7a 100644 --- a/i386/i386/cpu_number.c +++ b/i386/i386/cpu_number.c @@ -21,10 +21,16 @@ #include #include +extern int bspdone; + #if NCPUS > 1 int cpu_number(void) { int kernel_id, apic_id; + + if (bspdone == 0) + return 0; + apic_id = apic_get_current_cpu(); if (apic_id < 0) { printf("apic_get_current_cpu() failed, assuming BSP\n"); @@ -36,5 +42,7 @@ int cpu_number(void) printf("apic_get_cpu_kernel_id() failed, assuming BSP\n"); kernel_id = 0; } + + return kernel_id; } #endif -- 2.34.1
Re: [PATCH 2/5 gnumach] i386: Refactor int stacks to be per cpu for SMP
On 4/2/23 12:27, Almudena Garcia wrote: > But, added to interrupt stacks, the APs needs their own stacks once these are > running, to store data of the process which are executing. I thought this kind of stack is dynamically allocated by the thread manager (?) Damien
Re: [PATCH 2/5 gnumach] i386: Refactor int stacks to be per cpu for SMP
But, added to interrupt stacks, the APs needs their own stacks once these are running, to store data of the process which are executing. El sáb., 4 feb. 2023 2:24, Damien Zammit escribió: > Hi Almu, > > On 3/2/23 02:56, Almudena Garcia wrote: > > I already suggested move this to a function > > > > +#ifndef MACH_HYP > > +/* Turn paging on. > > + * TODO: Why does setting the WP bit here cause a crash? > > + */ > > +set_cr0(get_cr0() | CR0_PG /* | CR0_WP */); > > +set_cr0(get_cr0() & ~(CR0_CD | CR0_NW)); > > +if (CPU_HAS_FEATURE(CPU_FEATURE_PGE)) > > +set_cr4(get_cr4() | CR4_PGE); > > I moved this to a function called paging_enable() > > > > I miss the stack's memory reserve and assignation for AP processors, > which was usually make before startup these. Where are this? > > Interrupt stacks are pre-assigned by the compiler at a fixed location per > cpu. See "solid_intstack". > > Damien > >
Re: [PATCH 2/5 gnumach] i386: Refactor int stacks to be per cpu for SMP
Hi Almu, On 3/2/23 02:56, Almudena Garcia wrote: > I already suggested move this to a function > > +#ifndef MACH_HYP > + /* Turn paging on. > + * TODO: Why does setting the WP bit here cause a crash? > + */ > + set_cr0(get_cr0() | CR0_PG /* | CR0_WP */); > + set_cr0(get_cr0() & ~(CR0_CD | CR0_NW)); > + if (CPU_HAS_FEATURE(CPU_FEATURE_PGE)) > + set_cr4(get_cr4() | CR4_PGE); I moved this to a function called paging_enable() > I miss the stack's memory reserve and assignation for AP processors, which > was usually make before startup these. Where are this? Interrupt stacks are pre-assigned by the compiler at a fixed location per cpu. See "solid_intstack". Damien
[PATCH v3] i386: Refactor int stacks to be per cpu for SMP
This also serialises the AP bringup, so paging can be enabled per cpu one by one. Also-by: Almudena Garcia --- i386/i386/mp_desc.c | 230 i386/i386/mp_desc.h | 7 +- i386/i386at/boothdr.S | 18 +++- i386/i386at/ioapic.c| 5 +- i386/i386at/model_dep.c | 33 +++--- 5 files changed, 201 insertions(+), 92 deletions(-) diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c index bcf2fbe7..03b2ea68 100644 --- a/i386/i386/mp_desc.c +++ b/i386/i386/mp_desc.c @@ -24,25 +24,36 @@ * the rights to redistribute these changes. */ -#ifNCPUS > 1 - -#include - #include #include #include +#include +#include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include + #include #include +#include #include #include #include +#include +#include + /* * The i386 needs an interrupt stack to keep the PCB stack from being * overrun by interrupts. All interrupt stacks MUST lie at lower addresses @@ -52,20 +63,35 @@ /* * Addresses of bottom and top of interrupt stacks. */ -vm_offset_tinterrupt_stack[NCPUS]; vm_offset_tint_stack_top[NCPUS]; vm_offset_tint_stack_base[NCPUS]; -/* - * Barrier address. - */ -vm_offset_tint_stack_high; +/* Interrupt stack allocation */ +uint8_t solid_intstack[NCPUS*INTSTACK_SIZE] __aligned(NCPUS*INTSTACK_SIZE); + +void +interrupt_stack_alloc(void) +{ + int i; + + /* +* Set up pointers to the top of the interrupt stack. +*/ + + for (i = 0; i < NCPUS; i++) { + int_stack_base[i] = (vm_offset_t) &solid_intstack[i * INTSTACK_SIZE]; + int_stack_top[i] = (vm_offset_t) &solid_intstack[(i + 1) * INTSTACK_SIZE] - 4; + } +} +#ifNCPUS > 1 /* - * First cpu`s interrupt stack. + * Flag to mark SMP init by BSP complete */ -extern char_intstack[];/* bottom */ -extern char_eintstack[]; /* top */ +int bspdone; + +extern void *apboot, *apbootend; +extern volatile ApicLocalUnit* lapic; /* * Multiprocessor i386/i486 systems use a separate copy of the @@ -77,7 +103,7 @@ extern char _eintstack[]; /* top */ */ /* - * Allocated descriptor tables. + * Descriptor tables. */ struct mp_desc_table *mp_desc_table[NCPUS] = { 0 }; @@ -102,12 +128,13 @@ extern struct real_descriptor ldt[LDTSZ]; * Allocate and initialize the per-processor descriptor tables. */ -struct mp_desc_table * +int mp_desc_init(int mycpu) { struct mp_desc_table *mpt; + vm_offset_t mem; - if (mycpu == master_cpu) { + if (mycpu == 0) { /* * Master CPU uses the tables built at boot time. * Just set the TSS and GDT pointers. @@ -118,61 +145,28 @@ mp_desc_init(int mycpu) } else { /* -* Other CPUs allocate the table from the bottom of -* the interrupt stack. +* Allocate tables for other CPUs */ - mpt = (struct mp_desc_table *) interrupt_stack[mycpu]; + if (!init_alloc_aligned(sizeof(struct mp_desc_table), &mem)) + panic("not enough memory for descriptor tables"); + mpt = (struct mp_desc_table *)phystokv(mem); mp_desc_table[mycpu] = mpt; mp_ktss[mycpu] = &mpt->ktss; mp_gdt[mycpu] = mpt->gdt; /* -* Copy the tables +* Zero the tables */ - memcpy(mpt->idt, - idt, - sizeof(idt)); - memcpy(mpt->gdt, - gdt, - sizeof(gdt)); - memcpy(mpt->ldt, - ldt, - sizeof(ldt)); - memset(&mpt->ktss, 0, - sizeof(struct task_tss)); + memset(mpt->idt, 0, sizeof(idt)); + memset(mpt->gdt, 0, sizeof(gdt)); + memset(mpt->ldt, 0, sizeof(ldt)); + memset(&mpt->ktss, 0, sizeof(struct task_tss)); - /* -* Fix up the entries in the GDT to point to -* this LDT and this TSS. -*/ -#ifdef MACH_RING1 - panic("TODO %s:%d\n",__FILE__,__LINE__); -#else /* MACH_RING1 */ - _fill_gdt_sys_descriptor(mpt->gdt, KERNEL_LDT, - (unsigned)&mpt->ldt, - LDTSZ * sizeof(struct real_descriptor) - 1, - ACC_P|ACC_PL_K|ACC_LDT, 0); - _fill_gdt_sys_descriptor(mpt->gdt, KERNEL_TSS, - (unsigned)&mpt->ktss, - sizeof(struct task_tss) - 1, - ACC_P|ACC_PL_K|ACC_TSS, 0); - - mpt->ktss.tss.ss0 = KERNEL_DS; - mpt->ktss.tss.io_bit_map_offset = IOPB_INVAL; -
Mixing 32 and 64 bit userspace tasks (was: Re: [PATCH gnumach] Define rpc_vm_size_array_t and rpc_vm_offset_array_t)
Il 01/02/23 10:36, Sergey Bugaev ha scritto: Note that another way to handle the size conversion between rpc_* and regular types would be to add some new VM types to include/mach/message.h; in this case, the shrink/expand would happen in copyinmsg()/copyoutmsg() instead of the mig-generated code (as for mach ports), but this approach would require to plan for a staged introduction of this change. Actually, yes, that's what I've been thinking about. Currently vm_size_t & friends are conditionally (but statically) defined to either MACH_MSG_TYPE_INTEGER_32 or MACH_MSG_TYPE_INTEGER_64. But what if we also had MACH_MSG_TYPE_INTEGER_PTRSIZE (name TBD), which would be equivalent to MACH_MSG_TYPE_INTEGER_{32,64} for {32,64}-bit tasks; but the kernel would know about this and change its size accordingly when transferring messages between 64- and 32-bit tasks. A value sent as MACH_MSG_TYPE_INTEGER_32 is always received as MACH_MSG_TYPE_INTEGER_32, no matter if the intent was to send a pointer-sized value, whereas a 32-bit value sent by a 32-bit task as MACH_MSG_TYPE_INTEGER_PTRSIZE would get received as a 64-bit value, still MACH_MSG_TYPE_INTEGER_PTRSIZE, by a 64-bit task. While this shouldn't be a problem for normal data transfers, where the kernel already copies the data from one task to the other adjusting the size of vm fields, I wonder if there are cases where the virtual address is not supposed to be translated between tasks, e.g. if we really need to send a task-specific virtual address. For example, are there cases where a task allocates memory on behalf of another task? (except for the exec task) This would allow 32- and 64- bit tasks (including the kernel task) to communicate transparently, without requiring separate rpc_* versions of all the pointer-sized types. Possibly. Maybe. Uness there are a lot of subtler details to this, which there of course are. I think a more difficult case is the rpc_time_value_t type, but this case could be solved by adding yet another MACH_MSG_TYPE_TIME_VALUE value. However the problem exists for any struct type (which are just int[] of fixed size in mig), because there could be differences due to both alignment and pointer-type fields. So either the kernel knows all the data structures exchanged by user-space tasks, or the task needs to handle a message differently depending if the sender is a 32 or 64 bit task. Maybe this could be handled by the mig stubs, I'm not sure. The information about the sending task could be encoded in one of the unused bits of the msg header. Something similar to rpc_ types would still be needed for regular syscalls, but then they could be renamed to vm_offset_32_t and similar, since syscalls would have different entry points. But I'm sure it has been a conscious decision to go with the current design and not this way? For the parts that I wrote, the choice was based on some information that I found in the wiki, on irc and to some extent it seemed faster to implement. Considering the above issue with struct, I'm not sure how much a new vm type would simplify message handling. I'm also not arguing that mixing 32- and 64-bit tasks is worth supporting. This was a hard requirement for OS X, since they had to be able to run existing proprietary binaries unmodified. We build everything from source, so just having all of the userland be 64-bit (and fixing any issues we find on the way) sounds very viable. Using 32-bit win32 software via Wine has been the single reason to run 32-bit processes on my GNU/Linux system, but apparently that's now changing too (WoW64). And I don't know how relevant using Wine on the Hurd is anyway. Maybe one advantage could be a reduced memory usage for 32-bit subhurds, if we want also 64-bit subhurds on the same machine. Luca
Re: [PATCH v2 2/3 gnumach] linux: Keep existing timer interrupt handler for APIC
I applied it but moved the #ifndef APIC to inside restore_IRQ, to restore raising spl back to high, as the rest of the initialization code expects. Damien Zammit, le ven. 03 févr. 2023 10:01:55 +, a ecrit: > --- > linux/dev/arch/i386/kernel/irq.c | 2 +- > linux/dev/init/main.c| 2 ++ > 2 files changed, 3 insertions(+), 1 deletion(-) > > diff --git a/linux/dev/arch/i386/kernel/irq.c > b/linux/dev/arch/i386/kernel/irq.c > index 67feea84..b48d1312 100644 > --- a/linux/dev/arch/i386/kernel/irq.c > +++ b/linux/dev/arch/i386/kernel/irq.c > @@ -721,13 +721,13 @@ init_IRQ (void) >outb_p (PIT_C0 | PIT_SQUAREMODE | PIT_READMODE, PITCTL_PORT); >outb_p (latch & 0xff, PITCTR0_PORT); >outb (latch >> 8, PITCTR0_PORT); > -#endif > >/* > * Install our clock interrupt handler. > */ >old_clock_handler = ivect[0]; >ivect[0] = linux_timer_intr; > +#endif > >reserve_mach_irqs (); > > diff --git a/linux/dev/init/main.c b/linux/dev/init/main.c > index 6d853957..207724f3 100644 > --- a/linux/dev/init/main.c > +++ b/linux/dev/init/main.c > @@ -160,7 +160,9 @@ linux_init (void) >pcmcia_init (); > #endif > > +#ifndef APIC >restore_IRQ (); > +#endif > >linux_auto_config = 0; > } > -- > 2.34.1
Re: [PATCH v2 1/3 gnumach] pmap: Refactor temporary mapping functions
Applied, thanks! Damien Zammit, le ven. 03 févr. 2023 10:01:49 +, a ecrit: > --- > i386/i386at/model_dep.c | 73 +--- > i386/intel/pmap.c | 93 + > i386/intel/pmap.h | 6 +++ > 3 files changed, 101 insertions(+), 71 deletions(-) > > diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c > index fe11bffc..98408c06 100644 > --- a/i386/i386at/model_dep.c > +++ b/i386/i386at/model_dep.c > @@ -359,10 +359,6 @@ register_boot_data(const struct multiboot_raw_info *mbi) > static void > i386at_init(void) > { > - /* XXX move to intel/pmap.h */ > - extern pt_entry_t *kernel_page_dir; > - int i; > - > /* >* Initialize the PIC prior to any possible call to an spl. >*/ > @@ -448,47 +444,8 @@ i386at_init(void) >*/ > biosmem_setup(); > > - /* > - * We'll have to temporarily install a direct mapping > - * between physical memory and low linear memory, > - * until we start using our new kernel segment descriptors. > - */ > -#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS > - vm_offset_t delta = INIT_VM_MIN_KERNEL_ADDRESS - > LINEAR_MIN_KERNEL_ADDRESS; > - if ((vm_offset_t)(-delta) < delta) > - delta = (vm_offset_t)(-delta); > - int nb_direct = delta >> PDESHIFT; > - for (i = 0; i < nb_direct; i++) > - kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + > i] = > - > kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS) + i]; > -#endif > - /* We need BIOS memory mapped at 0xc & co for BIOS accesses */ > -#if VM_MIN_KERNEL_ADDRESS != 0 > - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - > VM_MIN_KERNEL_ADDRESS)] = > - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)]; > -#endif > + pmap_make_temporary_mapping(); > > -#ifdef MACH_PV_PAGETABLES > - for (i = 0; i < PDPNUM; i++) > - pmap_set_page_readonly_init((void*) kernel_page_dir + i * > INTEL_PGBYTES); > -#if PAE > - pmap_set_page_readonly_init(kernel_pmap->pdpbase); > -#endif /* PAE */ > -#endif /* MACH_PV_PAGETABLES */ > -#if PAE > -#ifdef __x86_64__ > - set_cr3((unsigned long)_kvtophys(kernel_pmap->l4base)); > -#else > - set_cr3((unsigned long)_kvtophys(kernel_pmap->pdpbase)); > -#endif > -#ifndef MACH_HYP > - if (!CPU_HAS_FEATURE(CPU_FEATURE_PAE)) > - panic("CPU doesn't have support for PAE."); > - set_cr4(get_cr4() | CR4_PAE); > -#endif /* MACH_HYP */ > -#else > - set_cr3((unsigned long)_kvtophys(kernel_page_dir)); > -#endif /* PAE */ > #ifndef MACH_HYP > /* Turn paging on. >* Also set the WP bit so that on 486 or better processors > @@ -520,33 +477,7 @@ i386at_init(void) > mp_desc_init(0); > #endif // NCPUS > > -#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS > - /* Get rid of the temporary direct mapping and flush it out of the TLB. > */ > - for (i = 0 ; i < nb_direct; i++) { > -#ifdef MACH_XEN > -#ifdef MACH_PSEUDO_PHYS > - if > (!hyp_mmu_update_pte(kv_to_ma(&kernel_page_dir[lin2pdenum_cont(VM_MIN_KERNEL_ADDRESS) > + i]), 0)) > -#else/* MACH_PSEUDO_PHYS */ > - if (hyp_do_update_va_mapping(VM_MIN_KERNEL_ADDRESS + i * > INTEL_PGBYTES, 0, UVMF_INVLPG | UVMF_ALL)) > -#endif /* MACH_PSEUDO_PHYS */ > - printf("couldn't unmap frame %d\n", i); > -#else/* MACH_XEN */ > - kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + > i] = 0; > -#endif /* MACH_XEN */ > - } > -#endif > - /* Keep BIOS memory mapped */ > -#if VM_MIN_KERNEL_ADDRESS != 0 > - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - > VM_MIN_KERNEL_ADDRESS)] = > - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)]; > -#endif > - > - /* Not used after boot, better give it back. */ > -#ifdef MACH_XEN > - hyp_free_page(0, (void*) VM_MIN_KERNEL_ADDRESS); > -#endif /* MACH_XEN */ > - > - flush_tlb(); > + pmap_remove_temporary_mapping(); > > #ifdef MACH_XEN > hyp_p2m_init(); > diff --git a/i386/intel/pmap.c b/i386/intel/pmap.c > index 0505cfa2..3c57d732 100644 > --- a/i386/intel/pmap.c > +++ b/i386/intel/pmap.c > @@ -3009,3 +3009,96 @@ pmap_unmap_page_zero (void) > #endif /* MACH_PV_PAGETABLES */ > } > #endif /* __i386__ */ > + > +void > +pmap_make_temporary_mapping(void) > +{ > + int i; > + > + /* > + * We'll have to temporarily install a direct mapping > + * between physical memory and low linear memory, > + * until we start using our new kernel segment descriptors. > + */ > +#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS > + vm_offset_t delta = INIT_VM_MIN_KERNEL_ADDRESS - > LINEAR_MIN_KERNEL_ADDRESS; > + if ((vm_offset_t)(-del
Re: [PATCHv2] libstdc++: Mark pieces of gnu-linux/os_support.h linux-specific
On Fri, 7 Oct 2022 at 21:45, Samuel Thibault wrote: > > This is notably needed because in glibc 2.34, the move of pthread functions > into libc.so happened for Linux only, not GNU/Hurd. > > The pthread_self() function can also always be used fine as it is on > GNU/Hurd. Sorry for the delay, I'm going to push this to trunk today. > > libstdc++-v3/ChangeLog: > > * config/os/gnu-linux/os_defines.h [!__linux__] > (_GLIBCXX_NATIVE_THREAD_ID, _GLIBCXX_GTHREAD_USE_WEAK): Do not > define. > > diff --git a/libstdc++-v3/config/os/gnu-linux/os_defines.h > b/libstdc++-v3/config/os/gnu-linux/os_defines.h > index c0caa21a013..4de93d752e1 100644 > --- a/libstdc++-v3/config/os/gnu-linux/os_defines.h > +++ b/libstdc++-v3/config/os/gnu-linux/os_defines.h > @@ -49,22 +49,24 @@ > // version dynamically in case it has changed since libstdc++ was configured. > #define _GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC __GLIBC_PREREQ(2,23) > > -#if __GLIBC_PREREQ(2, 27) > -// Since glibc 2.27 pthread_self() is usable without linking to libpthread. > -# define _GLIBCXX_NATIVE_THREAD_ID pthread_self() > -#else > +#ifdef __linux__ > +# if __GLIBC_PREREQ(2, 27) > +// Since glibc 2.27 Linux' pthread_self() is usable without linking to > libpthread. > +# define _GLIBCXX_NATIVE_THREAD_ID pthread_self() > +# else > // Before then it was in libc.so.6 but not libc.a, and always returns 0, > // which breaks the invariant this_thread::get_id() != thread::id{}. > // So only use it if we know the libpthread version is available. > // Otherwise use (__gthread_t)1 as the ID of the main (and only) thread. > -# define _GLIBCXX_NATIVE_THREAD_ID \ > - (__gthread_active_p() ? __gthread_self() : (__gthread_t)1) > -#endif > +# define _GLIBCXX_NATIVE_THREAD_ID \ > + (__gthread_active_p() ? __gthread_self() : (__gthread_t)1) > +# endif > > -#if __GLIBC_PREREQ(2, 34) > -// Since glibc 2.34 all pthreads functions are usable without linking to > +# if __GLIBC_PREREQ(2, 34) > +// Since glibc 2.34 all Linux pthreads functions are usable without linking > to > // libpthread. > -# define _GLIBCXX_GTHREAD_USE_WEAK 0 > +# define _GLIBCXX_GTHREAD_USE_WEAK 0 > +# endif > #endif > > #endif >
Re: [PATCH v2 3/3 gnumach] i386: Refactor int stacks to be per cpu for SMP
+#ifndef MACH_HYP +/* Turn paging on. + * TODO: Why does setting the WP bit here cause a crash? + */ +set_cr0(get_cr0() | CR0_PG /* | CR0_WP */); +set_cr0(get_cr0() & ~(CR0_CD | CR0_NW)); +if (CPU_HAS_FEATURE(CPU_FEATURE_PGE)) +set_cr4(get_cr4() | CR4_PGE); Again, you need some checks more. And, why not separate this in a function? Check my original function https://github.com/AlmuHS/GNUMach_SMP/blob/a31999c018c22d23402d3e02b5dfd595d4a29230/i386/i386/mp_desc.c#L365-L392 I copy its code here, if you don't want to follow the link void paging_setup(){ #if PAE set_cr3(pdpbase_addr); #ifndef MACH_HYP if (!CPU_HAS_FEATURE(CPU_FEATURE_PAE)) set_cr4(get_cr4() | CR4_PAE); #endif /* MACH_HYP */ #else set_cr3(kernel_page_dir_addr); #endif /* PAE */ #ifndef MACH_HYP /* Turn paging on. * Also set the WP bit so that on 486 or better processors * page-level write protection works in kernel mode. */ set_cr0(get_cr0() | CR0_PG | CR0_WP); set_cr0(get_cr0() & ~(CR0_CD | CR0_NW)); if (CPU_HAS_FEATURE(CPU_FEATURE_PGE)) set_cr4(get_cr4() | CR4_PGE); #endif /* MACH_HYP */ flush_instr_queue(); flush_tlb(); } El vie, 3 feb 2023 a las 11:03, Damien Zammit () escribió: > This also serialises the AP bringup, so paging can be enabled per cpu > one by one. > > Also-by: Almudena Garcia > --- > i386/i386/mp_desc.c | 226 > i386/i386/mp_desc.h | 7 +- > i386/i386at/boothdr.S | 18 +++- > i386/i386at/ioapic.c| 5 +- > i386/i386at/model_dep.c | 33 +++--- > 5 files changed, 197 insertions(+), 92 deletions(-) > > diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c > index bcf2fbe7..0db29291 100644 > --- a/i386/i386/mp_desc.c > +++ b/i386/i386/mp_desc.c > @@ -24,25 +24,36 @@ > * the rights to redistribute these changes. > */ > > -#ifNCPUS > 1 > - > -#include > - > #include > #include > #include > +#include > +#include > +#include > #include > #include > #include > > #include > #include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > #include > #include > +#include > #include > #include > #include > > +#include > +#include > + > /* > * The i386 needs an interrupt stack to keep the PCB stack from being > * overrun by interrupts. All interrupt stacks MUST lie at lower > addresses > @@ -52,20 +63,35 @@ > /* > * Addresses of bottom and top of interrupt stacks. > */ > -vm_offset_tinterrupt_stack[NCPUS]; > vm_offset_tint_stack_top[NCPUS]; > vm_offset_tint_stack_base[NCPUS]; > > -/* > - * Barrier address. > - */ > -vm_offset_tint_stack_high; > +/* Interrupt stack allocation */ > +uint8_t solid_intstack[NCPUS*INTSTACK_SIZE] > __aligned(NCPUS*INTSTACK_SIZE); > + > +void > +interrupt_stack_alloc(void) > +{ > + int i; > + > + /* > +* Set up pointers to the top of the interrupt stack. > +*/ > > + for (i = 0; i < NCPUS; i++) { > + int_stack_base[i] = (vm_offset_t) &solid_intstack[i * > INTSTACK_SIZE]; > + int_stack_top[i] = (vm_offset_t) &solid_intstack[(i + 1) * > INTSTACK_SIZE] - 4; > + } > +} > + > +#ifNCPUS > 1 > /* > - * First cpu`s interrupt stack. > + * Flag to mark SMP init by BSP complete > */ > -extern char_intstack[];/* bottom */ > -extern char_eintstack[]; /* top */ > +int bspdone; > + > +extern void *apboot, *apbootend; > +extern volatile ApicLocalUnit* lapic; > > /* > * Multiprocessor i386/i486 systems use a separate copy of the > @@ -77,7 +103,7 @@ extern char _eintstack[]; /* top */ > */ > > /* > - * Allocated descriptor tables. > + * Descriptor tables. > */ > struct mp_desc_table *mp_desc_table[NCPUS] = { 0 }; > > @@ -102,12 +128,13 @@ extern struct real_descriptor ldt[LDTSZ]; > * Allocate and initialize the per-processor descriptor tables. > */ > > -struct mp_desc_table * > +int > mp_desc_init(int mycpu) > { > struct mp_desc_table *mpt; > + vm_offset_t mem; > > - if (mycpu == master_cpu) { > + if (mycpu == 0) { > /* > * Master CPU uses the tables built at boot time. > * Just set the TSS and GDT pointers. > @@ -118,61 +145,28 @@ mp_desc_init(int mycpu) > } > else { > /* > -* Other CPUs allocate the table from the bottom of > -* the interrupt stack. > +* Allocate tables for other CPUs > */ > - mpt = (struct mp_desc_table *) interrupt_stack[mycpu]; > + if (!init_alloc_aligned(sizeof(struct mp_desc_table), > &mem)) > + panic("not enough memory for descriptor tables"); > + mpt = (struct mp_desc_table *)phystokv(mem); > > mp_desc_table[mycpu] = mpt; > m
[PATCH v2 3/3 gnumach] i386: Refactor int stacks to be per cpu for SMP
This also serialises the AP bringup, so paging can be enabled per cpu one by one. Also-by: Almudena Garcia --- i386/i386/mp_desc.c | 226 i386/i386/mp_desc.h | 7 +- i386/i386at/boothdr.S | 18 +++- i386/i386at/ioapic.c| 5 +- i386/i386at/model_dep.c | 33 +++--- 5 files changed, 197 insertions(+), 92 deletions(-) diff --git a/i386/i386/mp_desc.c b/i386/i386/mp_desc.c index bcf2fbe7..0db29291 100644 --- a/i386/i386/mp_desc.c +++ b/i386/i386/mp_desc.c @@ -24,25 +24,36 @@ * the rights to redistribute these changes. */ -#ifNCPUS > 1 - -#include - #include #include #include +#include +#include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include + #include #include +#include #include #include #include +#include +#include + /* * The i386 needs an interrupt stack to keep the PCB stack from being * overrun by interrupts. All interrupt stacks MUST lie at lower addresses @@ -52,20 +63,35 @@ /* * Addresses of bottom and top of interrupt stacks. */ -vm_offset_tinterrupt_stack[NCPUS]; vm_offset_tint_stack_top[NCPUS]; vm_offset_tint_stack_base[NCPUS]; -/* - * Barrier address. - */ -vm_offset_tint_stack_high; +/* Interrupt stack allocation */ +uint8_t solid_intstack[NCPUS*INTSTACK_SIZE] __aligned(NCPUS*INTSTACK_SIZE); + +void +interrupt_stack_alloc(void) +{ + int i; + + /* +* Set up pointers to the top of the interrupt stack. +*/ + for (i = 0; i < NCPUS; i++) { + int_stack_base[i] = (vm_offset_t) &solid_intstack[i * INTSTACK_SIZE]; + int_stack_top[i] = (vm_offset_t) &solid_intstack[(i + 1) * INTSTACK_SIZE] - 4; + } +} + +#ifNCPUS > 1 /* - * First cpu`s interrupt stack. + * Flag to mark SMP init by BSP complete */ -extern char_intstack[];/* bottom */ -extern char_eintstack[]; /* top */ +int bspdone; + +extern void *apboot, *apbootend; +extern volatile ApicLocalUnit* lapic; /* * Multiprocessor i386/i486 systems use a separate copy of the @@ -77,7 +103,7 @@ extern char _eintstack[]; /* top */ */ /* - * Allocated descriptor tables. + * Descriptor tables. */ struct mp_desc_table *mp_desc_table[NCPUS] = { 0 }; @@ -102,12 +128,13 @@ extern struct real_descriptor ldt[LDTSZ]; * Allocate and initialize the per-processor descriptor tables. */ -struct mp_desc_table * +int mp_desc_init(int mycpu) { struct mp_desc_table *mpt; + vm_offset_t mem; - if (mycpu == master_cpu) { + if (mycpu == 0) { /* * Master CPU uses the tables built at boot time. * Just set the TSS and GDT pointers. @@ -118,61 +145,28 @@ mp_desc_init(int mycpu) } else { /* -* Other CPUs allocate the table from the bottom of -* the interrupt stack. +* Allocate tables for other CPUs */ - mpt = (struct mp_desc_table *) interrupt_stack[mycpu]; + if (!init_alloc_aligned(sizeof(struct mp_desc_table), &mem)) + panic("not enough memory for descriptor tables"); + mpt = (struct mp_desc_table *)phystokv(mem); mp_desc_table[mycpu] = mpt; mp_ktss[mycpu] = &mpt->ktss; mp_gdt[mycpu] = mpt->gdt; /* -* Copy the tables +* Zero the tables */ - memcpy(mpt->idt, - idt, - sizeof(idt)); - memcpy(mpt->gdt, - gdt, - sizeof(gdt)); - memcpy(mpt->ldt, - ldt, - sizeof(ldt)); - memset(&mpt->ktss, 0, - sizeof(struct task_tss)); + memset(mpt->idt, 0, sizeof(idt)); + memset(mpt->gdt, 0, sizeof(gdt)); + memset(mpt->ldt, 0, sizeof(ldt)); + memset(&mpt->ktss, 0, sizeof(struct task_tss)); - /* -* Fix up the entries in the GDT to point to -* this LDT and this TSS. -*/ -#ifdef MACH_RING1 - panic("TODO %s:%d\n",__FILE__,__LINE__); -#else /* MACH_RING1 */ - _fill_gdt_sys_descriptor(mpt->gdt, KERNEL_LDT, - (unsigned)&mpt->ldt, - LDTSZ * sizeof(struct real_descriptor) - 1, - ACC_P|ACC_PL_K|ACC_LDT, 0); - _fill_gdt_sys_descriptor(mpt->gdt, KERNEL_TSS, - (unsigned)&mpt->ktss, - sizeof(struct task_tss) - 1, - ACC_P|ACC_PL_K|ACC_TSS, 0); - - mpt->ktss.tss.ss0 = KERNEL_DS; - mpt->ktss.tss.io_bit_map_offset = IOPB_INVAL; -
[PATCH v2 2/3 gnumach] linux: Keep existing timer interrupt handler for APIC
--- linux/dev/arch/i386/kernel/irq.c | 2 +- linux/dev/init/main.c| 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/linux/dev/arch/i386/kernel/irq.c b/linux/dev/arch/i386/kernel/irq.c index 67feea84..b48d1312 100644 --- a/linux/dev/arch/i386/kernel/irq.c +++ b/linux/dev/arch/i386/kernel/irq.c @@ -721,13 +721,13 @@ init_IRQ (void) outb_p (PIT_C0 | PIT_SQUAREMODE | PIT_READMODE, PITCTL_PORT); outb_p (latch & 0xff, PITCTR0_PORT); outb (latch >> 8, PITCTR0_PORT); -#endif /* * Install our clock interrupt handler. */ old_clock_handler = ivect[0]; ivect[0] = linux_timer_intr; +#endif reserve_mach_irqs (); diff --git a/linux/dev/init/main.c b/linux/dev/init/main.c index 6d853957..207724f3 100644 --- a/linux/dev/init/main.c +++ b/linux/dev/init/main.c @@ -160,7 +160,9 @@ linux_init (void) pcmcia_init (); #endif +#ifndef APIC restore_IRQ (); +#endif linux_auto_config = 0; } -- 2.34.1
[PATCH v2 1/3 gnumach] pmap: Refactor temporary mapping functions
--- i386/i386at/model_dep.c | 73 +--- i386/intel/pmap.c | 93 + i386/intel/pmap.h | 6 +++ 3 files changed, 101 insertions(+), 71 deletions(-) diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c index fe11bffc..98408c06 100644 --- a/i386/i386at/model_dep.c +++ b/i386/i386at/model_dep.c @@ -359,10 +359,6 @@ register_boot_data(const struct multiboot_raw_info *mbi) static void i386at_init(void) { - /* XXX move to intel/pmap.h */ - extern pt_entry_t *kernel_page_dir; - int i; - /* * Initialize the PIC prior to any possible call to an spl. */ @@ -448,47 +444,8 @@ i386at_init(void) */ biosmem_setup(); - /* -* We'll have to temporarily install a direct mapping -* between physical memory and low linear memory, -* until we start using our new kernel segment descriptors. -*/ -#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS - vm_offset_t delta = INIT_VM_MIN_KERNEL_ADDRESS - LINEAR_MIN_KERNEL_ADDRESS; - if ((vm_offset_t)(-delta) < delta) - delta = (vm_offset_t)(-delta); - int nb_direct = delta >> PDESHIFT; - for (i = 0; i < nb_direct; i++) - kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + i] = - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS) + i]; -#endif - /* We need BIOS memory mapped at 0xc & co for BIOS accesses */ -#if VM_MIN_KERNEL_ADDRESS != 0 - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] = - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)]; -#endif + pmap_make_temporary_mapping(); -#ifdef MACH_PV_PAGETABLES - for (i = 0; i < PDPNUM; i++) - pmap_set_page_readonly_init((void*) kernel_page_dir + i * INTEL_PGBYTES); -#if PAE - pmap_set_page_readonly_init(kernel_pmap->pdpbase); -#endif /* PAE */ -#endif /* MACH_PV_PAGETABLES */ -#if PAE -#ifdef __x86_64__ - set_cr3((unsigned long)_kvtophys(kernel_pmap->l4base)); -#else - set_cr3((unsigned long)_kvtophys(kernel_pmap->pdpbase)); -#endif -#ifndefMACH_HYP - if (!CPU_HAS_FEATURE(CPU_FEATURE_PAE)) - panic("CPU doesn't have support for PAE."); - set_cr4(get_cr4() | CR4_PAE); -#endif /* MACH_HYP */ -#else - set_cr3((unsigned long)_kvtophys(kernel_page_dir)); -#endif /* PAE */ #ifndefMACH_HYP /* Turn paging on. * Also set the WP bit so that on 486 or better processors @@ -520,33 +477,7 @@ i386at_init(void) mp_desc_init(0); #endif // NCPUS -#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS - /* Get rid of the temporary direct mapping and flush it out of the TLB. */ - for (i = 0 ; i < nb_direct; i++) { -#ifdef MACH_XEN -#ifdef MACH_PSEUDO_PHYS - if (!hyp_mmu_update_pte(kv_to_ma(&kernel_page_dir[lin2pdenum_cont(VM_MIN_KERNEL_ADDRESS) + i]), 0)) -#else /* MACH_PSEUDO_PHYS */ - if (hyp_do_update_va_mapping(VM_MIN_KERNEL_ADDRESS + i * INTEL_PGBYTES, 0, UVMF_INVLPG | UVMF_ALL)) -#endif /* MACH_PSEUDO_PHYS */ - printf("couldn't unmap frame %d\n", i); -#else /* MACH_XEN */ - kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + i] = 0; -#endif /* MACH_XEN */ - } -#endif - /* Keep BIOS memory mapped */ -#if VM_MIN_KERNEL_ADDRESS != 0 - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS)] = - kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS)]; -#endif - - /* Not used after boot, better give it back. */ -#ifdef MACH_XEN - hyp_free_page(0, (void*) VM_MIN_KERNEL_ADDRESS); -#endif /* MACH_XEN */ - - flush_tlb(); + pmap_remove_temporary_mapping(); #ifdef MACH_XEN hyp_p2m_init(); diff --git a/i386/intel/pmap.c b/i386/intel/pmap.c index 0505cfa2..3c57d732 100644 --- a/i386/intel/pmap.c +++ b/i386/intel/pmap.c @@ -3009,3 +3009,96 @@ pmap_unmap_page_zero (void) #endif /* MACH_PV_PAGETABLES */ } #endif /* __i386__ */ + +void +pmap_make_temporary_mapping(void) +{ + int i; + + /* +* We'll have to temporarily install a direct mapping +* between physical memory and low linear memory, +* until we start using our new kernel segment descriptors. +*/ +#if INIT_VM_MIN_KERNEL_ADDRESS != LINEAR_MIN_KERNEL_ADDRESS + vm_offset_t delta = INIT_VM_MIN_KERNEL_ADDRESS - LINEAR_MIN_KERNEL_ADDRESS; + if ((vm_offset_t)(-delta) < delta) + delta = (vm_offset_t)(-delta); + int nb_direct = delta >> PDESHIFT; + for (i = 0; i < nb_direct; i++) + kernel_page_dir[lin2pdenum_cont(INIT_VM_MIN_KERNEL_ADDRESS) + i] = + kernel_page_dir[lin2pdenum_cont(LINEAR_MIN_KERNEL_ADDRESS) + i]; +#endif +