bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v4 3/3 gnumach] apic: Add extended feature registers for loca


From: Samuel Thibault
Subject: Re: [PATCH v4 3/3 gnumach] apic: Add extended feature registers for local apic unit
Date: Sun, 22 Dec 2024 02:46:36 +0100

Applied, thanks!

Damien Zammit via Bug reports for the GNU Hurd, le dim. 22 déc. 2024 01:43:44 
+0000, a ecrit:
> Add workaround for broken systems that advertise 8 bit APIC ids
> but only match IPIs on 4 bits of the APIC id.
> ---
>  i386/i386/apic.c              | 28 +++++++++++++++++++++++++++-
>  i386/i386/apic.h              | 15 ++++++++++++++-
>  i386/i386/cpu_number.h        |  3 +++
>  i386/i386/cpuboot.S           |  1 +
>  i386/i386at/acpi_parse_apic.c |  5 ++++-
>  i386/i386at/ioapic.c          |  8 ++++++--
>  6 files changed, 55 insertions(+), 5 deletions(-)
> 
> diff --git a/i386/i386/apic.c b/i386/i386/apic.c
> index e0941c6a..77d555b5 100644
> --- a/i386/i386/apic.c
> +++ b/i386/i386/apic.c
> @@ -46,6 +46,13 @@ int cpu_id_lut[UINT8_MAX + 1] = {0};
>  
>  ApicInfo apic_data;
>  
> +/* xAPIC: This is supposed to be an 8 bit mask.  On some platforms it needs 
> to be a
> + * lower 4 bit mask because the chipset only matches on 4 bits of the id 
> when doing IPIs.
> + * The cpuid accessor and lapic may report full 8 bit id so always & with 
> this mask when
> + * reading the APIC id.  Increases to 8 bits if no workaround is required.
> +*/
> +uint8_t apic_id_mask = 0xf;
> +
>  /*
>   * apic_data_init: initialize the apic_data structures to preliminary values.
>   * Reserve memory to the lapic list dynamic vector.
> @@ -206,7 +213,7 @@ apic_get_current_cpu(void)
>      eax = 1;
>      ecx = 0;
>      cpuid(eax, ebx, ecx, edx);
> -    return (ebx >> 24);
> +    return (ebx >> 24) & apic_id_mask;
>  }
>  
>  
> @@ -322,6 +329,25 @@ lapic_disable(void)
>      lapic->spurious_vector.r &= ~LAPIC_ENABLE;
>  }
>  
> +void
> +fix_apic_id_mask(void)
> +{
> +    if (lapic->version.r & APIC_VERSION_HAS_EXT_APIC_SPACE) {
> +        /* Extended registers beyond 0x3f0 are present */
> +        if (lapic->extended_feature.r & APIC_EXT_FEATURE_HAS_8BITID) {
> +            /* 8 bit APIC ids are supported on this local APIC */
> +            if (!(lapic->extended_control.r & APIC_EXT_CTRL_ENABLE_8BITID)) {
> +                printf("WARNING: Only 4 bit APIC ids\n");
> +                apic_id_mask = 0xf;
> +                return;
> +            }
> +        }
> +    }
> +
> +    printf("8 bit APIC ids\n");
> +    apic_id_mask = 0xff;
> +}
> +
>  void
>  lapic_setup(void)
>  {
> diff --git a/i386/i386/apic.h b/i386/i386/apic.h
> index 5b38bfba..92fb900a 100644
> --- a/i386/i386/apic.h
> +++ b/i386/i386/apic.h
> @@ -189,8 +189,20 @@ typedef struct ApicLocalUnit {
>          ApicReg reserved3d;              /* 0x3d0 */
>          ApicReg divider_config;          /* 0x3e0 */
>          ApicReg reserved3f;              /* 0x3f0 */
> +        ApicReg extended_feature;        /* 0x400  Present if version 
> extended apic space bit is set */
> +        ApicReg extended_control;        /* 0x410 */
> +        ApicReg specific_eoi;            /* 0x420 */
>  } ApicLocalUnit;
>  
> +#define APIC_VERSION_HAS_EXT_APIC_SPACE      (1 << 31)
> +#define APIC_VERSION_HAS_DIRECTED_EOI        (1 << 24)
> +
> +#define APIC_EXT_FEATURE_HAS_SEOI    (1 << 1)
> +#define APIC_EXT_FEATURE_HAS_8BITID  (1 << 2)
> +
> +#define APIC_EXT_CTRL_ENABLE_SEOI    (1 << 1)
> +#define APIC_EXT_CTRL_ENABLE_8BITID  (1 << 2)
> +
>  typedef struct IoApicData {
>          uint8_t  apic_id;
>          uint8_t  ngsis;
> @@ -244,6 +256,7 @@ int apic_get_total_gsis(void);
>  void picdisable(void);
>  void lapic_eoi(void);
>  void ioapic_irq_eoi(int pin);
> +void fix_apic_id_mask(void);
>  void lapic_setup(void);
>  void lapic_disable(void);
>  void lapic_enable(void);
> @@ -261,6 +274,7 @@ extern void intnull(int unit);
>  extern volatile ApicLocalUnit* lapic;
>  extern int cpu_id_lut[];
>  extern uint32_t *hpet_addr;
> +extern uint8_t apic_id_mask;
>  
>  #endif
>  
> @@ -292,7 +306,6 @@ extern uint32_t *hpet_addr;
>  #define LAPIC_TIMER_DIVIDE_8           2
>  #define LAPIC_TIMER_DIVIDE_16          3
>  #define LAPIC_TIMER_BASEDIV            0x100000
> -#define LAPIC_HAS_DIRECTED_EOI         0x1000000
>  
>  #define NINTR                          64 /* Max 32 GSIs on each of two 
> IOAPICs */
>  #define IOAPIC_FIXED                   0
> diff --git a/i386/i386/cpu_number.h b/i386/i386/cpu_number.h
> index 547e0498..0c0ec189 100644
> --- a/i386/i386/cpu_number.h
> +++ b/i386/i386/cpu_number.h
> @@ -46,6 +46,7 @@
>       movl    %cs:lapic, reg          ;\
>       movl    %cs:APIC_ID(reg), reg   ;\
>       shrl    $24, reg                ;\
> +     andl    %cs:apic_id_mask, reg   ;\
>       movl    %cs:CX(cpu_id_lut, reg), reg    ;\
>  
>  /* Fast version, requires a stack */
> @@ -60,6 +61,7 @@
>       movl    $1, %eax        ;\
>       cpuid                   ;\
>       shrl    $24, %ebx       ;\
> +     andl    %cs:apic_id_mask, %ebx  ;\
>       movl    %cs:CX(cpu_id_lut, %ebx), %esi  ;\
>       popl    %edx            ;\
>       popl    %ecx            ;\
> @@ -79,6 +81,7 @@
>       movl    $1, %eax        ;\
>       cpuid                   ;\
>       shrl    $24, %ebx       ;\
> +     andl    %cs:apic_id_mask, %ebx  ;\
>       movl    %cs:CX(cpu_id_lut, %ebx), %esi  ;\
>       popq    %rdx            ;\
>       popq    %rcx            ;\
> diff --git a/i386/i386/cpuboot.S b/i386/i386/cpuboot.S
> index 6ba7aa42..76de8714 100644
> --- a/i386/i386/cpuboot.S
> +++ b/i386/i386/cpuboot.S
> @@ -171,6 +171,7 @@ apboot_jmp_offset:
>       movl    $1, %eax
>       cpuid
>       shrl    $24, %ebx
> +     andl    %cs:apic_id_mask, %ebx
>       movl    %cs:CX(cpu_id_lut, %ebx), %ebp
>  
>       /* Copy first gdt descriptor and gdt to cpu-th area */
> diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c
> index ae92ee2e..bac5d04d 100644
> --- a/i386/i386at/acpi_parse_apic.c
> +++ b/i386/i386at/acpi_parse_apic.c
> @@ -378,7 +378,7 @@ acpi_apic_add_lapic(struct acpi_apic_lapic *lapic_entry)
>      /* If cpu flag is correct */
>      if (lapic_entry->flags & (ACPI_LAPIC_FLAG_ENABLED | 
> ACPI_LAPIC_FLAG_CAPABLE)) {
>          /* Add cpu to processors' list. */
> -        apic_add_cpu(lapic_entry->apic_id);
> +        apic_add_cpu(lapic_entry->apic_id & apic_id_mask);
>      }
>  
>  }
> @@ -541,6 +541,9 @@ acpi_apic_setup(struct acpi_apic *apic)
>          return ACPI_NO_LAPIC;
>  
>      apic_lapic_init(lapic_unit);
> +
> +    fix_apic_id_mask();
> +
>      acpi_apic_parse_table(apic);
>  
>      ncpus = apic_get_numcpus();
> diff --git a/i386/i386at/ioapic.c b/i386/i386at/ioapic.c
> index 845d1249..5dd2de2e 100644
> --- a/i386/i386at/ioapic.c
> +++ b/i386/i386at/ioapic.c
> @@ -366,7 +366,7 @@ void
>  ioapic_configure(void)
>  {
>      /* Assume first IO APIC maps to GSI base 0 */
> -    int gsi, apic = 0, bsp = 0, pin;
> +    int gsi, apic = 0, pin;
>      IrqOverrideData *irq_over;
>      int timer_gsi;
>      int version = ioapic_version(apic);
> @@ -387,7 +387,11 @@ ioapic_configure(void)
>      entry.both.delvmode = IOAPIC_FIXED;
>      entry.both.destmode = IOAPIC_PHYSICAL;
>      entry.both.mask = IOAPIC_MASK_DISABLED;
> -    entry.both.dest = apic_get_cpu_apic_id(bsp);
> +    /* This does not use apic_id_mask because
> +     * the IOAPIC seems to use what is actually set
> +     * in lapic's apic_id register.
> +     */
> +    entry.both.dest = lapic->apic_id.r >> 24;
>  
>      for (pin = 0; pin < 16; pin++) {
>          gsi = pin;
> -- 
> 2.45.2
> 
> 
> 

-- 
Samuel
 PS> Salut ! J'ai un sujet de philo à vous soumettre : "Suffit-il
 PS> d'observer pour connaître" Idées + plan Merçi
 Oui, ya qu'a t'observer pour connaître le fait que tu es une feignasse.
 -+- FF in: Guide du Neuneu d'Usenet - Neuneu fait de la philo -+-



reply via email to

[Prev in Thread] Current Thread [Next in Thread]