Skip to content

Commit

Permalink
LoongArch: Add FDT booting support from efi system table
Browse files Browse the repository at this point in the history
Since commit 40cd01a("efi/loongarch: libstub: remove dependency on
flattened DT"), we can parse the FDT from efi system table.

And now, LoongArch is coming to support booting with FDT, so we add the
relevant booting support as well as parameter parsing.

Signed-off-by: Binbin Zhou <[email protected]>
Signed-off-by: Huacai Chen <[email protected]>
  • Loading branch information
Binbin Zhou authored and chenhuacai committed Dec 14, 2022
1 parent a275a82 commit 88d4d95
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 7 deletions.
2 changes: 2 additions & 0 deletions arch/loongarch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ config LOONGARCH
select MODULES_USE_ELF_RELA if MODULES
select NEED_PER_CPU_EMBED_FIRST_CHUNK
select NEED_PER_CPU_PAGE_FIRST_CHUNK
select OF
select OF_EARLY_FLATTREE
select PCI
select PCI_DOMAINS_GENERIC
select PCI_ECAM if ACPI
Expand Down
1 change: 1 addition & 0 deletions arch/loongarch/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

void __init efi_init(void);
void __init efi_runtime_init(void);
void __init *efi_fdt_pointer(void);
void efifb_setup_from_dmi(struct screen_info *si, const char *opt);

#define ARCH_EFI_IRQ_FLAGS_MASK 0x00000004 /* Bit 2: CSR.CRMD.IE */
Expand Down
1 change: 1 addition & 0 deletions arch/loongarch/include/asm/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

extern unsigned long eentry;
extern unsigned long tlbrentry;
extern char init_command_line[COMMAND_LINE_SIZE];
extern void tlb_init(int cpu);
extern void cpu_cache_init(void);
extern void cache_error_setup(void);
Expand Down
11 changes: 9 additions & 2 deletions arch/loongarch/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/memblock.h>
#include <linux/of_fdt.h>
#include <linux/serial_core.h>
#include <asm/io.h>
#include <asm/numa.h>
Expand Down Expand Up @@ -145,14 +146,14 @@ void __init acpi_boot_table_init(void)
* If acpi_disabled, bail out
*/
if (acpi_disabled)
return;
goto fdt_earlycon;

/*
* Initialize the ACPI boot-time table parser.
*/
if (acpi_table_init()) {
disable_acpi();
return;
goto fdt_earlycon;
}

loongson_sysconf.boot_cpu_id = read_csr_cpuid();
Expand All @@ -164,6 +165,12 @@ void __init acpi_boot_table_init(void)

/* Do not enable ACPI SPCR console by default */
acpi_parse_spcr(earlycon_acpi_spcr_enable, false);

return;

fdt_earlycon:
if (earlycon_acpi_spcr_enable)
early_init_dt_scan_chosen_stdout();
}

#ifdef CONFIG_ACPI_NUMA
Expand Down
15 changes: 14 additions & 1 deletion arch/loongarch/kernel/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,29 @@ static unsigned long efi_nr_tables;
static unsigned long efi_config_table;

static unsigned long __initdata boot_memmap = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata fdt_pointer = EFI_INVALID_TABLE_ADDR;

static efi_system_table_t *efi_systab;
static efi_config_table_type_t arch_tables[] __initdata = {
{LINUX_EFI_BOOT_MEMMAP_GUID, &boot_memmap, "MEMMAP" },
{DEVICE_TREE_GUID, &fdt_pointer, "FDTPTR" },
{},
};

void __init *efi_fdt_pointer(void)
{
if (!efi_systab)
return NULL;

if (fdt_pointer == EFI_INVALID_TABLE_ADDR)
return NULL;

return early_memremap_ro(fdt_pointer, SZ_64K);
}

void __init efi_runtime_init(void)
{
if (!efi_enabled(EFI_BOOT))
if (!efi_enabled(EFI_BOOT) || !efi_systab->runtime)
return;

if (efi_runtime_disabled()) {
Expand Down
2 changes: 2 additions & 0 deletions arch/loongarch/kernel/env.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <asm/early_ioremap.h>
#include <asm/bootinfo.h>
#include <asm/loongson.h>
#include <asm/setup.h>

u64 efi_system_table;
struct loongson_system_configuration loongson_sysconf;
Expand All @@ -27,6 +28,7 @@ void __init init_environ(void)
clear_bit(EFI_BOOT, &efi.flags);

strscpy(boot_command_line, cmdline, COMMAND_LINE_SIZE);
strscpy(init_command_line, cmdline, COMMAND_LINE_SIZE);
early_memunmap(cmdline, COMMAND_LINE_SIZE);

efi_system_table = fw_arg2;
Expand Down
17 changes: 16 additions & 1 deletion arch/loongarch/kernel/numa.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,21 @@ static void __init numa_default_distance(void)
}
}

/*
* fake_numa_init() - For Non-ACPI systems
* Return: 0 on success, -errno on failure.
*/
static int __init fake_numa_init(void)
{
phys_addr_t start = memblock_start_of_DRAM();
phys_addr_t end = memblock_end_of_DRAM() - 1;

node_set(0, numa_nodes_parsed);
pr_info("Faking a node at [mem %pap-%pap]\n", &start, &end);

return numa_add_memblk(0, start, end + 1);
}

int __init init_numa_memory(void)
{
int i;
Expand All @@ -404,7 +419,7 @@ int __init init_numa_memory(void)
memset(&numa_meminfo, 0, sizeof(numa_meminfo));

/* Parse SRAT and SLIT if provided by firmware. */
ret = acpi_numa_init();
ret = acpi_disabled ? fake_numa_init() : acpi_numa_init();
if (ret < 0)
return ret;

Expand Down
62 changes: 61 additions & 1 deletion arch/loongarch/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include <linux/sizes.h>
#include <linux/device.h>
#include <linux/dma-map-ops.h>
#include <linux/libfdt.h>
#include <linux/of_fdt.h>
#include <linux/of_address.h>
#include <linux/swiotlb.h>

#include <asm/addrspace.h>
Expand Down Expand Up @@ -69,6 +72,7 @@ static const char dmi_empty_string[] = " ";
*
* These are initialized so they are in the .data section
*/
char init_command_line[COMMAND_LINE_SIZE] __initdata;

static int num_standard_resources;
static struct resource *standard_resources;
Expand Down Expand Up @@ -253,6 +257,58 @@ static void __init arch_parse_crashkernel(void)
#endif
}

static void __init fdt_setup(void)
{
#ifdef CONFIG_OF_EARLY_FLATTREE
void *fdt_pointer;

/* ACPI-based systems do not require parsing fdt */
if (acpi_os_get_root_pointer())
return;

/* Look for a device tree configuration table entry */
fdt_pointer = efi_fdt_pointer();
if (!fdt_pointer || fdt_check_header(fdt_pointer))
return;

early_init_dt_scan(fdt_pointer);
early_init_fdt_reserve_self();

max_low_pfn = PFN_PHYS(memblock_end_of_DRAM());
#endif
}

static void __init bootcmdline_init(char **cmdline_p)
{
/*
* If CONFIG_CMDLINE_FORCE is enabled then initializing the command line
* is trivial - we simply use the built-in command line unconditionally &
* unmodified.
*/
if (IS_ENABLED(CONFIG_CMDLINE_FORCE)) {
strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
goto out;
}

#ifdef CONFIG_OF_FLATTREE
/*
* If CONFIG_CMDLINE_BOOTLOADER is enabled and we are in FDT-based system,
* the boot_command_line will be overwritten by early_init_dt_scan_chosen().
* So we need to append init_command_line (the original copy of boot_command_line)
* to boot_command_line.
*/
if (initial_boot_params) {
if (boot_command_line[0])
strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);

strlcat(boot_command_line, init_command_line, COMMAND_LINE_SIZE);
}
#endif

out:
*cmdline_p = boot_command_line;
}

void __init platform_init(void)
{
arch_reserve_vmcore();
Expand All @@ -265,6 +321,7 @@ void __init platform_init(void)
acpi_gbl_use_default_register_widths = false;
acpi_boot_table_init();
#endif
unflatten_and_copy_device_tree();

#ifdef CONFIG_NUMA
init_numa_memory();
Expand Down Expand Up @@ -297,6 +354,8 @@ static void __init arch_mem_init(char **cmdline_p)

check_kernel_sections_mem();

early_init_fdt_scan_reserved_mem();

/*
* In order to reduce the possibility of kernel panic when failed to
* get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate
Expand Down Expand Up @@ -422,12 +481,13 @@ static void __init prefill_possible_map(void)
void __init setup_arch(char **cmdline_p)
{
cpu_probe();
*cmdline_p = boot_command_line;

init_environ();
efi_init();
fdt_setup();
memblock_init();
pagetable_init();
bootcmdline_init(cmdline_p);
parse_early_param();
reserve_initrd_mem();

Expand Down
34 changes: 34 additions & 0 deletions arch/loongarch/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,42 @@ irqreturn_t loongson_ipi_interrupt(int irq, void *dev)
return IRQ_HANDLED;
}

static void __init fdt_smp_setup(void)
{
#ifdef CONFIG_OF
unsigned int cpu, cpuid;
struct device_node *node = NULL;

for_each_of_cpu_node(node) {
if (!of_device_is_available(node))
continue;

cpuid = of_get_cpu_hwid(node, 0);
if (cpuid >= nr_cpu_ids)
continue;

if (cpuid == loongson_sysconf.boot_cpu_id) {
cpu = 0;
numa_add_cpu(cpu);
} else {
cpu = cpumask_next_zero(-1, cpu_present_mask);
}

num_processors++;
set_cpu_possible(cpu, true);
set_cpu_present(cpu, true);
__cpu_number_map[cpuid] = cpu;
__cpu_logical_map[cpu] = cpuid;
}

loongson_sysconf.nr_cpus = num_processors;
#endif
}

void __init loongson_smp_setup(void)
{
fdt_smp_setup();

cpu_data[0].core = cpu_logical_map(0) % loongson_sysconf.cores_per_package;
cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package;

Expand Down
7 changes: 5 additions & 2 deletions arch/loongarch/pci/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ void pcibios_add_bus(struct pci_bus *bus)

int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{
struct pci_config_window *cfg = bridge->bus->sysdata;
struct acpi_device *adev = to_acpi_device(cfg->parent);
struct acpi_device *adev = NULL;
struct device *bus_dev = &bridge->bus->dev;
struct pci_config_window *cfg = bridge->bus->sysdata;

if (!acpi_disabled)
adev = to_acpi_device(cfg->parent);

ACPI_COMPANION_SET(&bridge->dev, adev);
set_dev_node(bus_dev, pa_to_nid(cfg->res.start));
Expand Down

0 comments on commit 88d4d95

Please sign in to comment.