I attach new set of patches, fixing the latest errors

El jue., 13 ago. 2020 a las 0:41, Samuel Thibault (<samuel.thiba...@gnu.org>)
escribió:

> Almudena Garcia, le jeu. 13 août 2020 00:35:36 +0200, a ecrit:
> > > Users do need that to understand what's happening.
> > But, if by any reason, the machine has more than cpu but the detection
> fails,
> > could be interesting to advise about the system being running with an
> only cpu.
> > It's not?
>
> Yes. But your current code is printing an error also in other cases.
>
> Samuel
>
From 0f3be00652da041440c9e51e1881eff532671392 Mon Sep 17 00:00:00 2001
From: Almudena Garcia <liberamenso10...@gmail.com>
Date: Thu, 13 Aug 2020 15:11:33 +0200
Subject: [PATCH 1/3] smp: Add APIC finder and parser

To find the processors, It's necessary to find the APIC (MADT) table
This table is found inside ACPI tables.

This set of functions find the MADT table, and parse it to find the APIC structures
and register it in the kernel.

*acpi_parse_apic.h: ACPI structures and function prototypes.
*acpi_parse_apic.c: ACPI/APIC function definitions.
---
 i386/Makefrag.am              |   2 +
 i386/i386at/acpi_parse_apic.c | 543 ++++++++++++++++++++++++++++++++++
 i386/i386at/acpi_parse_apic.h | 164 ++++++++++
 3 files changed, 709 insertions(+)
 create mode 100644 i386/i386at/acpi_parse_apic.c
 create mode 100644 i386/i386at/acpi_parse_apic.h

diff --git a/i386/Makefrag.am b/i386/Makefrag.am
index 035fd34d..0f788f30 100644
--- a/i386/Makefrag.am
+++ b/i386/Makefrag.am
@@ -32,6 +32,8 @@ libkernel_a_SOURCES += \
 
 if PLATFORM_at
 libkernel_a_SOURCES += \
+	i386/i386at/acpi_parse_apic.h \
+	i386/i386at/acpi_parse_apic.c \
 	i386/i386at/boothdr.S \
 	i386/i386at/com.c \
 	i386/i386at/com.h \
diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c
new file mode 100644
index 00000000..55b6a09b
--- /dev/null
+++ b/i386/i386at/acpi_parse_apic.c
@@ -0,0 +1,543 @@
+/* acpi_parse_apic.h - ACPI-MADT table parser. Source file
+   Copyright (C) 2018 Juan Bosco Garcia
+   Copyright (C) 2019 2020 Almudena Garcia Jurado-Centurion
+   Written by Juan Bosco Garcia and Almudena Garcia Jurado-Centurion
+
+   This file is part of Min_SMP.
+
+   Min_SMP is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   Min_SMP is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+#include <string.h>         /* memcmp, memcpy... */
+
+#include <include/stdint.h> /* uint16_t, uint32_t... */
+
+#include <mach/machine.h>   /* machine_slot */
+
+#include <kern/printf.h>    /* printf */
+#include <kern/debug.h>
+#include <i386/vm_param.h>  /* phystokv */
+#include <i386/apic.h>      /* lapic, ioapic... */
+#include <i386at/acpi_parse_apic.h>
+#include <vm/vm_kern.h>
+
+static struct acpi_apic *apic_madt = NULL;
+
+/*
+ * acpi_print_info: shows by screen the ACPI's rsdp and rsdt virtual address
+ * and the number of entries stored in RSDT table.
+ *
+ * Receives as input the references of RSDP and RSDT tables,
+ * and the number of entries stored in RSDT.
+ */
+void
+acpi_print_info(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, int acpi_rsdt_n)
+{
+
+    printf("ACPI:\n");
+    printf(" rsdp = %x; rsdp->rsdt_addr = %x\n", rsdp, rsdp->rsdt_addr);
+    printf(" rsdt = %x; rsdt->length = %x (n = %x)\n", rsdt, rsdt->header.length,
+           acpi_rsdt_n);
+}
+
+/*
+ * acpi_checksum: calculates the checksum of an ACPI table.
+ * Receives as input the virtual address of the table.
+ *
+ * Returns 0 if success, other value if error.
+ */
+static uint8_t
+acpi_checksum(void *addr, uint32_t length)
+{
+    uint8_t *bytes = addr;
+    uint8_t checksum = 0;
+    unsigned int i;
+
+    /* Sum all bytes of addr */
+    for (i = 0; i < length; i++)
+        checksum += bytes[i];
+
+    return checksum;
+}
+
+/*
+ * acpi_check_signature: check if a signature match with the signature of its table.
+ *
+ * Receive as parameter both signatures: table signature, the signature which needs to check,
+ * and real signature, the genuine signature of the table.
+ *
+ * Return 0 if success, other if error.
+ */
+
+static int
+acpi_check_signature(uint8_t table_signature[], uint8_t real_signature[], uint8_t length)
+{
+    return memcmp(table_signature, real_signature, length);
+}
+
+
+/*
+ * acpi_check_rsdp:
+ * check if the RDSP "candidate" table is the real RSDP table.
+ *
+ * Compare the table signature with the ACPI signature for this table
+ * and check is the checksum is correct.
+ *
+ * Receives as input the reference of RSDT table.
+ *
+ * Preconditions: RSDP pointer must not be NULL.
+ *
+ * Returns 0 if correct.
+ */
+static int8_t
+acpi_check_rsdp(struct acpi_rsdp *rsdp)
+{
+    uint32_t checksum;
+    int is_rsdp;
+
+    /* Check if rsdp signature match with the ACPI RSDP signature. */
+    is_rsdp = acpi_check_signature(rsdp->signature, ACPI_RSDP_SIG, 8*sizeof(uint8_t));
+
+    if (is_rsdp != ACPI_SUCCESS)
+        return ACPI_BAD_SIGNATURE;
+
+    /* If match, calculates rdsp checksum and check It. */
+    checksum = acpi_checksum(rsdp, sizeof(struct acpi_rsdp));
+
+    if (checksum != 0)
+        return ACPI_BAD_CHECKSUM;
+
+    return ACPI_SUCCESS;
+}
+
+/*
+ * acpi_check_rsdp_align: check if the RSDP address is aligned.
+ * Preconditions: The address must not be NULL
+ *
+ * Returns ACPI_SUCCESS (0) if success, ACPI_BAD_ALIGN if error
+ */
+
+static int8_t
+acpi_check_rsdp_align(void *addr)
+{
+    /* check alignment. */
+    if ((uint32_t)addr & (ACPI_RSDP_ALIGN-1))
+        return ACPI_BAD_ALIGN;
+
+    return ACPI_SUCCESS;
+}
+
+/*
+ * acpi_search_rsdp: search the rsdp table in a memory range.
+ *
+ * Receives as input the initial virtual address, and the lenght
+ * of memory range.
+ *
+ * Preconditions: The start address (addr) must be aligned.
+ *
+ * Returns the reference to rsdp structure if success, NULL if failure.
+ */
+static struct acpi_rsdp*
+acpi_search_rsdp(void *addr, uint32_t length)
+{
+    void *end;
+
+    /* Search RDSP in memory space between addr and addr+lenght. */
+    for (end = addr+length; addr < end; addr += ACPI_RSDP_ALIGN) {
+
+        /* Check if the current memory block stores the RDSP. */
+        if ((addr != NULL) && (acpi_check_rsdp(addr) == ACPI_SUCCESS)) {
+            /* If yes, return RSDP address */
+            return (struct acpi_rsdp*) addr;
+        }
+    }
+
+    return NULL;
+}
+
+/*
+ * acpi_get_rsdp: tries to find the RSDP table,
+ * searching It in many memory ranges, as It's written in ACPI Specification.
+ *
+ * Returns the reference to RDSP structure if success, NULL if failure.
+ */
+struct acpi_rsdp*
+acpi_get_rsdp(void)
+{
+    struct acpi_rsdp *rsdp = NULL;
+    uint16_t *start = 0x0;
+    uint32_t base = 0x0;
+
+    /* EDBA start address. */
+    start = (uint16_t*) phystokv(0x040e);
+    base = *start;
+
+    if (base != 0) { /* Memory check. */
+
+        base <<= 4; /* base = base * 16 */
+
+        /* check alignment. */
+        if (acpi_check_rsdp_align(base) == ACPI_BAD_ALIGN)
+            return NULL;
+
+        /* Search the RSDP in first 1024 bytes from EDBA. */
+        rsdp = acpi_search_rsdp((void*)base,1024);
+    }
+
+    if (rsdp == NULL) {
+        /* If RSDP isn't in EDBA, search in the BIOS read-only memory space between 0E0000h and 0FFFFFh */
+        rsdp = acpi_search_rsdp((void*) 0x0e0000, 0x100000 - 0x0e0000);
+    }
+
+    return rsdp;
+}
+
+/*
+ * acpi_check_rsdt: check if the RSDT initial address is correct
+ * checking its checksum.
+ *
+ * Receives as input a reference for the RSDT "candidate" table.
+ * Returns 0 if success.
+ *
+ * Preconditions: rsdp must not be NULL.
+ *
+ */
+static int
+acpi_check_rsdt(struct acpi_rsdt *rsdt)
+{
+    uint8_t checksum;
+
+    checksum = acpi_checksum(rsdt, rsdt->header.length);
+
+    if (checksum != 0)
+        return ACPI_BAD_CHECKSUM;
+
+    return ACPI_SUCCESS;
+}
+
+/*
+ * acpi_get_rsdt: Get RSDT table reference from RSDP entries.
+ *
+ * Receives as input a reference for RSDP table
+ * and a reference to store the number of entries of RSDT.
+ *
+ * Returns the reference to RSDT table if success, NULL if error.
+ */
+static struct acpi_rsdt*
+acpi_get_rsdt(struct acpi_rsdp *rsdp, int* acpi_rsdt_n)
+{
+    phys_addr_t rsdt_phys;
+    struct acpi_rsdt *rsdt = NULL;
+    int acpi_check;
+    int signature_check;
+
+    /* Get rsdt address from rsdp table. */
+    rsdt_phys = rsdp->rsdt_addr;
+    rsdt = (struct acpi_rsdt*) kmem_map_aligned_table(rsdt_phys, sizeof(struct acpi_rsdt), VM_PROT_READ);
+
+    /* Check if the RSDT mapping is fine. */
+    if (rsdt == NULL)
+        return NULL;
+
+    /* Check is rsdt signature is equals to ACPI RSDT signature. */
+    signature_check = acpi_check_signature(rsdt->header.signature, ACPI_RSDT_SIG,
+                                           4*sizeof(uint8_t));
+
+    if (signature_check != ACPI_SUCCESS)
+        return NULL;
+
+    /* Check if rsdt is correct. */
+    acpi_check = acpi_check_rsdt(rsdt);
+
+    if (acpi_check != ACPI_SUCCESS)
+        return NULL;
+
+    /* Calculated number of elements stored in rsdt. */
+    *acpi_rsdt_n = (rsdt->header.length - sizeof(rsdt->header))
+                   / sizeof(rsdt->entry[0]);
+
+    return rsdt;
+}
+
+/*
+ * acpi_get_apic: get MADT/APIC table from RSDT entries.
+ *
+ * Receives as input the RSDT initial address,
+ * and the number of entries of RSDT table.
+ *
+ * Returns a reference to APIC/MADT table if success, NULL if failure.
+ */
+static struct acpi_apic*
+acpi_get_apic(struct acpi_rsdt *rsdt, int acpi_rsdt_n)
+{
+    struct acpi_dhdr *descr_header;
+    int check_signature;
+
+    /* Search APIC entries in rsdt table. */
+    for (int i = 0; i < acpi_rsdt_n; i++) {
+        descr_header = (struct acpi_dhdr*) kmem_map_aligned_table(rsdt->entry[i], sizeof(struct acpi_dhdr),
+                                                                  VM_PROT_READ | VM_PROT_WRITE);
+
+        /* Check if the entry contains an APIC. */
+        check_signature = acpi_check_signature(descr_header->signature, ACPI_APIC_SIG, 4*sizeof(uint8_t));
+
+        if (check_signature == ACPI_SUCCESS) {
+            /* If yes, return the APIC. */
+            return (struct acpi_apic*) descr_header;
+        }
+    }
+
+    return NULL;
+}
+
+/*
+ * acpi_add_lapic: add a new Local APIC to cpu_to_lapic array
+ * and increase the number of cpus.
+ *
+ * Receives as input the Local APIC entry in MADT/APIC table.
+ */
+static void
+acpi_apic_add_lapic(struct acpi_apic_lapic *lapic_entry)
+{
+    /* If cpu flag is correct */
+    if (lapic_entry->flags & 0x1) {
+        /* Add cpu to processors' list. */
+        apic_add_cpu(lapic_entry->apic_id);
+    }
+
+}
+
+/*
+ * apic_add_ioapic: add a new IOAPIC to IOAPICS array
+ * and increase the number of IOAPIC.
+ *
+ * Receives as input the IOAPIC entry in MADT/APIC table.
+ */
+
+static void
+acpi_apic_add_ioapic(struct acpi_apic_ioapic *ioapic_entry)
+{
+    int ret_value = 0;
+    IoApicData io_apic;
+
+    /* Fill IOAPIC structure with its main fields */
+    io_apic.apic_id = ioapic_entry->apic_id;
+    io_apic.addr = ioapic_entry->addr;
+    io_apic.base = ioapic_entry->base;
+
+    /* Insert IOAPIC in the list. */
+    apic_add_ioapic(io_apic);
+}
+
+
+/*
+ * apic_add_ioapic: add a new IOAPIC to IOAPICS list
+ * and increase the number of IOAPIC.
+ *
+ * Receives as input the IOAPIC entry in MADT/APIC table.
+ */
+
+static void
+acpi_apic_add_irq_override(struct acpi_apic_irq_override* irq_override)
+{
+    IrqOverrideData irq_over;
+
+    /* Fills IRQ override structure with its fields */
+    irq_over.bus = irq_override->bus;
+    irq_over.irq = irq_override->irq;
+    irq_over.gsi = irq_override->gsi;
+    irq_over.flags = irq_override->flags;
+
+    /* Insert IRQ override in the list */
+    apic_add_irq_override(irq_over);
+}
+
+
+/*
+ * apic_parse_table: parse the MADT/APIC table.
+ *
+ * Read the APIC/MADT table entry to entry,
+ * registering the APIC structures (Local APIC, IOAPIC or IRQ override) entries in their lists.
+ */
+
+static int
+acpi_apic_parse_table(struct acpi_apic *apic)
+{
+    int ret_value = 0;
+    struct acpi_apic_dhdr *apic_entry = NULL;
+    uint32_t end = 0;
+    uint8_t numcpus = 1;
+
+    /* Get the address of first APIC entry */
+    apic_entry = (struct acpi_apic_dhdr*) apic->entry;
+
+    /* Get the end address of APIC table */
+    end = (uint32_t) apic + apic->header.length;
+
+    /* Initialize number of cpus */
+    numcpus = apic_get_numcpus();
+
+    /* Search in APIC entry. */
+    while ((uint32_t)apic_entry < end) {
+        struct acpi_apic_lapic *lapic_entry;
+        struct acpi_apic_ioapic *ioapic_entry;
+        struct acpi_apic_irq_override *irq_override_entry;
+
+        /* Check entry type. */
+        switch(apic_entry->type) {
+
+        /* If APIC entry is a CPU's Local APIC. */
+        case ACPI_APIC_ENTRY_LAPIC:
+            if(numcpus < NCPUS) {
+                /* Store Local APIC data. */
+                lapic_entry = (struct acpi_apic_lapic*) apic_entry;
+                acpi_apic_add_lapic(lapic_entry);
+            }
+            break;
+
+        /* If APIC entry is an IOAPIC. */
+        case ACPI_APIC_ENTRY_IOAPIC:
+
+            /* Store IOAPIC data. */
+            ioapic_entry = (struct acpi_apic_ioapic*) apic_entry;
+            acpi_apic_add_ioapic(ioapic_entry);
+
+            break;
+
+        /* If APIC entry is a IRQ Override. */
+        case ACPI_APIC_ENTRY_IRQ_OVERRIDE:
+
+            /* Store IRQ Override data. */
+            irq_override_entry = (struct acpi_apic_irq_override*) apic_entry;
+            acpi_apic_add_irq_override(irq_override_entry);
+            break;
+
+        }
+
+        /* Get next APIC entry. */
+        apic_entry = (struct acpi_apic_dhdr*)((uint32_t) apic_entry
+                                              + apic_entry->length);
+
+        /* Update number of cpus. */
+        numcpus = apic_get_numcpus();
+    }
+
+    return ACPI_SUCCESS;
+}
+
+
+/*
+ * acpi_apic_setup: parses the APIC/MADT table, to find the Local APIC and IOAPIC structures
+ * and the common address for Local APIC.
+ *
+ * Receives as input a reference for APIC/MADT table.
+ * Returns 0 if success.
+ *
+ * Fills the cpu_to_lapic and ioapics array, indexed by Kernel ID
+ * with a relationship between Kernel ID and APIC ID,
+ * and map the Local APIC common address, to fill the lapic reference.
+ *
+ * Precondition: The APIC pointer must not be NULL
+ */
+
+static int
+acpi_apic_setup(struct acpi_apic *apic)
+{
+    int apic_checksum;
+    ApicLocalUnit* lapic;
+    uint8_t ncpus, nioapics;
+
+    /* Check the checksum of the APIC */
+    apic_checksum = acpi_checksum(apic, apic->header.length);
+
+    if(apic_checksum != 0)
+        return ACPI_BAD_CHECKSUM;
+
+    /* map common lapic address */
+    lapic = kmem_map_aligned_table(apic->lapic_addr, sizeof(ApicLocalUnit), VM_PROT_READ);
+
+    if (lapic == NULL)
+        return ACPI_NO_LAPIC;
+
+    apic_lapic_init(lapic);
+    acpi_apic_parse_table(apic);
+
+    ncpus = apic_get_numcpus();
+    nioapics = apic_get_num_ioapics();
+
+    if (ncpus == 0 || nioapics == 0 || ncpus > NCPUS)
+        return ACPI_APIC_FAILURE;
+
+    /* Refit the apic-cpu array. */
+    if(ncpus < NCPUS) {
+        int refit = apic_refit_cpulist();
+        if (refit != -0)
+            return ACPI_FIT_FAILURE;
+    }
+
+    return ACPI_SUCCESS;
+}
+
+/*
+ * acpi_apic_init: find the MADT/APIC table in ACPI tables
+ * and parses It to find Local APIC and IOAPIC structures.
+ * Each Local APIC stores the info and control structores for a cpu.
+ * The IOAPIC controls the communication of the processors with the I/O devices.
+ *
+ * Returns 0 if success, -1 if error.
+ */
+int
+acpi_apic_init(void)
+{
+    struct acpi_rsdp *rsdp = 0;
+    struct acpi_rsdt *rsdt = 0;
+    int acpi_rsdt_n;
+    int ret_acpi_setup;
+    int apic_init_success = 0;
+
+    /* Try to get the RSDP pointer. */
+    rsdp = acpi_get_rsdp();
+    if (rsdp == NULL)
+        return ACPI_NO_RSDP;
+
+    /* Try to get the RSDT pointer. */
+    rsdt = acpi_get_rsdt(rsdp, &acpi_rsdt_n);
+    if (rsdt == NULL)
+        return ACPI_NO_RSDT;
+
+    /* Try to get the APIC table pointer. */
+    apic_madt = acpi_get_apic(rsdt, acpi_rsdt_n);
+    if (apic_madt == NULL)
+        return ACPI_NO_APIC;
+
+    /* Print the ACPI tables addresses. */
+    acpi_print_info(rsdp, rsdt, acpi_rsdt_n);
+
+    apic_init_success = apic_data_init();
+    if (apic_init_success != ACPI_SUCCESS)
+        return ACPI_APIC_FAILURE;
+
+    /*
+     * Starts the parsing of APIC table, to find the APIC structures.
+     * and enumerate them. This function also find the common Local APIC address.
+     */
+    ret_acpi_setup = acpi_apic_setup(apic_madt);
+    if (ret_acpi_setup != ACPI_SUCCESS)
+        return ret_acpi_setup;
+
+    /* Prints a table with the list of each cpu and each IOAPIC with its APIC ID. */
+    apic_print_info();
+
+    return ACPI_SUCCESS;
+}
diff --git a/i386/i386at/acpi_parse_apic.h b/i386/i386at/acpi_parse_apic.h
new file mode 100644
index 00000000..1cfcc9ae
--- /dev/null
+++ b/i386/i386at/acpi_parse_apic.h
@@ -0,0 +1,164 @@
+/* acpi_parse_apic.h - ACPI-MADT table parser. Header file
+   Copyright (C) 2018 Juan Bosco Garcia
+   Copyright (C) 2019 2020 Almudena Garcia Jurado-Centurion
+   Written by Juan Bosco Garcia and Almudena Garcia Jurado-Centurion
+
+   This file is part of Min_SMP.
+
+   Min_SMP is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   Min_SMP is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+#ifndef __ACPI_H__
+#define __ACPI_H__
+
+#include <include/stdint.h>
+
+enum ACPI_RETURN {
+    ACPI_BAD_CHECKSUM = -1,
+    ACPI_BAD_ALIGN = -2,
+    ACPI_NO_RSDP = -3,
+    ACPI_NO_RSDT = -4,
+    ACPI_BAD_SIGNATURE = -5,
+    ACPI_NO_APIC = -6,
+    ACPI_NO_LAPIC = -7,
+    ACPI_APIC_FAILURE = -8,
+    ACPI_FIT_FAILURE = -9,
+    ACPI_SUCCESS = 0,
+};
+
+#define ACPI_RSDP_ALIGN 16
+#define ACPI_RSDP_SIG "RSD PTR "
+
+struct acpi_rsdp {
+    uint8_t  	signature[8];
+    uint8_t  	checksum;
+    uint8_t  	oem_id[6];
+    uint8_t  	revision[1];
+    uint32_t 	rsdt_addr;
+} __attribute__((__packed__));
+
+
+/*
+ * RSDT Entry Header
+ *
+ * Header which stores the descriptors of tables pointed from RDSP's Entry Field
+ * Includes the signature of the table, to identify each table.
+ *
+ * In MADT, the signature is 'APIC'.
+ */
+struct acpi_dhdr {
+    uint8_t		signature[4];
+    uint32_t	length;
+    uint8_t  	revision;
+    uint8_t  	checksum;
+    uint8_t  	oem_id[6];
+    uint8_t  	oem_table_id[8];
+    uint32_t 	oem_revision;
+    uint8_t  	creator_id[4];
+    uint32_t 	creator_revision;
+} __attribute__((__packed__));
+
+
+#define ACPI_RSDT_SIG "RSDT"
+
+struct acpi_rsdt {
+    struct acpi_dhdr 	header;
+    uint32_t 			entry[0];
+} __attribute__((__packed__));
+
+/* APIC table signature. */
+#define ACPI_APIC_SIG "APIC"
+
+/* Types value for MADT entries: Local APIC, IOAPIC and IRQ Override. */
+enum ACPI_APIC_ENTRY_TYPE {
+    ACPI_APIC_ENTRY_LAPIC = 0,
+    ACPI_APIC_ENTRY_IOAPIC = 1,
+    ACPI_APIC_ENTRY_IRQ_OVERRIDE  = 2,
+    ACPI_APIC_ENTRY_NONMASK_IRQ = 4
+};
+
+/*
+ * APIC descriptor header
+ * Define the type of the structure (Local APIC, I/O APIC or others).
+ * Type: Local APIC (0), I/O APIC (1).
+ */
+struct acpi_apic_dhdr {
+    uint8_t 	type;
+    uint8_t 	length;
+} __attribute__((__packed__));
+
+
+/*
+ * Multiple APIC Description Table (MADT)
+ *
+ * Describes the APIC structures which exist in the machine.
+ * Includes the common address where Local APIC is mapped in main memory.
+ *
+ * Entry field stores the descriptors of APIC structures.
+ */
+struct acpi_apic {
+    struct   	acpi_dhdr header;       /* Header, which stores the descriptor for RDST's Entry field. */
+    uint32_t 	lapic_addr;             /* Local Interrupt Controller Address. */
+    uint32_t 	flags;
+    struct acpi_apic_dhdr entry[0];     /* Interrupt Controller Structure */
+} __attribute__((__packed__));
+
+/*
+ * Processor Local APIC Structure
+ *
+ * Stores information about APIC ID, flags and ACPI Processor UID
+ */
+
+struct acpi_apic_lapic {
+    struct      acpi_apic_dhdr header;
+    uint8_t     processor_id;           /* ACPI Processor UID */
+    uint8_t     apic_id;
+    uint32_t    flags;
+} __attribute__((__packed__));
+
+
+/*
+ * I/O APIC Structure
+ *
+ * Stores information about APIC ID, and I/O APIC tables
+ */
+
+struct acpi_apic_ioapic {
+    struct      acpi_apic_dhdr header;
+    uint8_t     apic_id;
+    uint8_t     reserved;
+    uint32_t    addr;
+    uint32_t    base;
+} __attribute__((__packed__));
+
+/*
+ * IRQ Override structure
+ *
+ * Stores information about IRQ override, with busses and IRQ.
+ */
+
+struct acpi_apic_irq_override {
+    struct acpi_apic_dhdr header;
+    uint8_t     bus;
+    uint8_t     irq;
+    uint32_t    gsi;
+    uint16_t    flags;
+} __attribute__((__packed__));
+
+int acpi_apic_init(void);
+void acpi_print_info(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, int acpi_rsdt_n);
+
+
+#endif /* __ACPI_H__ */
+
-- 
2.28.0

From 46494874241135f753eebdd4003194f5bd7160e1 Mon Sep 17 00:00:00 2001
From: Almudena Garcia <liberamenso10...@gmail.com>
Date: Thu, 13 Aug 2020 15:23:13 +0200
Subject: [PATCH 2/3] smp: Add generic smp pseudoclass

This pseudoclass generalize the initialization and access of SMP data,
allowing expands it to other architectures. In x86, the functions calls to apic functions.

*kern/smp.c: Source file. Implements a interface to load the SMP functions for the current architecture.
*kern/smp.h: Header file. Add declaration for smp_data structure.
*i386/i386/smp.c: Source file. Implements a set of functions to manage the SMP actions in i386
*i386/i386/smp.h: Header file. Add declarations for SMP functions in i386.
---
 Makefrag.am      |  2 ++
 i386/Makefrag.am |  2 ++
 i386/i386/smp.c  | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
 i386/i386/smp.h  | 22 ++++++++++++++++++++
 kern/smp.c       | 49 +++++++++++++++++++++++++++++++++++++++++++
 kern/smp.h       | 24 +++++++++++++++++++++
 6 files changed, 153 insertions(+)
 create mode 100644 i386/i386/smp.c
 create mode 100644 i386/i386/smp.h
 create mode 100644 kern/smp.c
 create mode 100644 kern/smp.h

diff --git a/Makefrag.am b/Makefrag.am
index ea612275..fef1e000 100644
--- a/Makefrag.am
+++ b/Makefrag.am
@@ -195,6 +195,8 @@ libkernel_a_SOURCES += \
 	kern/refcount.h \
 	kern/slab.c \
 	kern/slab.h \
+	kern/smp.h \
+	kern/smp.c \
 	kern/sched.h \
 	kern/sched_prim.c \
 	kern/sched_prim.h \
diff --git a/i386/Makefrag.am b/i386/Makefrag.am
index 0f788f30..73df45f4 100644
--- a/i386/Makefrag.am
+++ b/i386/Makefrag.am
@@ -132,6 +132,8 @@ libkernel_a_SOURCES += \
 	i386/i386/seg.c \
 	i386/i386/seg.h \
 	i386/i386/setjmp.h \
+	i386/i386/smp.h \
+	i386/i386/smp.c \
 	i386/i386/spl.S \
 	i386/i386/spl.h \
 	i386/i386/strings.c \
diff --git a/i386/i386/smp.c b/i386/i386/smp.c
new file mode 100644
index 00000000..eaea2563
--- /dev/null
+++ b/i386/i386/smp.c
@@ -0,0 +1,54 @@
+/* smp.h - i386 SMP controller for Mach
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   Written by Almudena Garcia Jurado-Centurion
+
+   This file is part of GNU Mach.
+
+   GNU Mach is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Mach is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+#include <i386/i386/apic.h>
+#include <i386/i386/smp.h>
+#include <i386/i386at/acpi_parse_apic.h>
+
+#include <kern/smp.h>
+
+
+/*
+ * smp_data_init: initialize smp_data structure
+ * Must be called after smp_init(), once all APIC structures
+ * has been initialized
+ */
+static void smp_data_init(void)
+{
+    uint8_t numcpus = apic_get_numcpus();
+    smp_set_numcpus(numcpus);
+}
+
+/*
+ * smp_init: initialize the SMP support, starting the cpus searching
+ * and enumeration.
+ */
+int smp_init(void)
+{
+    int apic_success;
+
+    apic_success = acpi_apic_init();
+    if (apic_success == ACPI_SUCCESS) {
+        smp_data_init();
+    }
+
+    return apic_success;
+}
+
diff --git a/i386/i386/smp.h b/i386/i386/smp.h
new file mode 100644
index 00000000..a1ed33c9
--- /dev/null
+++ b/i386/i386/smp.h
@@ -0,0 +1,22 @@
+/* smp.h - i386 SMP controller for Mach. Header file
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   Written by Almudena Garcia Jurado-Centurion
+
+   This file is part of GNU Mach.
+
+   GNU Mach is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Mach is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+int smp_init(void);
+
diff --git a/kern/smp.c b/kern/smp.c
new file mode 100644
index 00000000..295f7031
--- /dev/null
+++ b/kern/smp.c
@@ -0,0 +1,49 @@
+/* smp.c - Template for generic SMP controller for Mach.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   Written by Almudena Garcia Jurado-Centurion
+
+   This file is part of GNU Mach.
+
+   GNU Mach is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Mach is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+#include <kern/smp.h>
+#include <machine/smp.h>
+#include <stdint.h>
+
+struct smp_data {
+    uint8_t num_cpus;
+} smp_info;
+
+/*
+ * smp_set_numcpus: initialize the number of cpus in smp_info structure
+ */
+
+void smp_set_numcpus(uint8_t numcpus)
+{
+   smp_info.num_cpus = numcpus;
+}
+
+/*
+ * smp_get_numcpus: returns the number of cpus existing in the machine
+ */
+uint8_t smp_get_numcpus(void)
+{
+   uint8_t numcpus = smp_info.num_cpus;
+
+   if (numcpus == 0)
+      return 1; /* Although SMP doesn't find cpus, always there are at least one. */
+   else
+      return numcpus;
+}
diff --git a/kern/smp.h b/kern/smp.h
new file mode 100644
index 00000000..44e96f39
--- /dev/null
+++ b/kern/smp.h
@@ -0,0 +1,24 @@
+/* smp.h - Template for generic SMP controller for Mach. Header file
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   Written by Almudena Garcia Jurado-Centurion
+
+   This file is part of GNU Mach.
+
+   GNU Mach is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Mach is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. */
+
+#include <stdint.h>
+
+void smp_set_numcpus(uint8_t numcpus);
+uint8_t smp_get_numcpus(void);
-- 
2.28.0

From 73e977210bfad6a75b923f591f5ba059021e89cc Mon Sep 17 00:00:00 2001
From: Almudena Garcia <liberamenso10...@gmail.com>
Date: Thu, 13 Aug 2020 15:30:35 +0200
Subject: [PATCH 3/3] model_dep.c: Add smp_init call

if NCPUS > 1, call to smp_init to start the search and enumeration of the cpus

*i386/i386/model_dep.c (machine_init): add smp_init() call
---
 i386/i386at/model_dep.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c
index aaeed807..a13b46af 100644
--- a/i386/i386at/model_dep.c
+++ b/i386/i386at/model_dep.c
@@ -42,7 +42,6 @@
 #include <mach/machine/multiboot.h>
 #include <mach/xen.h>
 
-#include <i386/vm_param.h>
 #include <kern/assert.h>
 #include <kern/cpu_number.h>
 #include <kern/debug.h>
@@ -50,6 +49,7 @@
 #include <kern/macros.h>
 #include <kern/printf.h>
 #include <kern/startup.h>
+#include <kern/smp.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <vm/vm_page.h>
@@ -62,6 +62,7 @@
 #include <i386/pit.h>
 #include <i386/pmap.h>
 #include <i386/proc_reg.h>
+#include <i386/vm_param.h>
 #include <i386/locore.h>
 #include <i386/model_dep.h>
 #include <i386at/autoconf.h>
@@ -72,6 +73,7 @@
 #include <i386at/kd.h>
 #include <i386at/rtc.h>
 #include <i386at/model_dep.h>
+
 #ifdef	MACH_XEN
 #include <xen/console.h>
 #include <xen/store.h>
@@ -170,6 +172,10 @@ void machine_init(void)
 	linux_init();
 #endif
 
+#if NCPUS > 1
+	smp_init();
+#endif /* NCPUS > 1 */
+
 	/*
 	 * Find the devices
 	 */
-- 
2.28.0

Reply via email to