LoongArch: Old BPI compatibility

Upstream: no

Signed-off-by: liuyun <liuyun@loongson.cn>
Signed-off-by: Ming Wang <wangming01@loongson.cn>
This commit is contained in:
liuyun 2023-12-02 10:08:31 +08:00 committed by aurelianliu
parent eae789a871
commit 4fe09071db
19 changed files with 844 additions and 26 deletions

View File

@ -124,6 +124,7 @@ extern unsigned long vm_map_base;
#define PCI_IOSIZE SZ_32M
#define ISA_IOSIZE SZ_16K
#define IO_SPACE_LIMIT (PCI_IOSIZE - 1)
#define ISA_PHY_IOBASE LOONGSON_LIO_BASE
#define PHYS_LINK_KADDR PHYSADDR(VMLINUX_LOAD_ADDRESS)

View File

@ -6,6 +6,7 @@
#define _ASM_LOONGARCH_EFI_H
#include <linux/efi.h>
#include <asm/early_ioremap.h>
void __init efi_init(void);
void __init efi_runtime_init(void);

View File

@ -9,6 +9,7 @@ obj-y += head.o cpu-probe.o cacheinfo.o env.o setup.o entry.o genex.o \
traps.o irq.o idle.o process.o dma.o mem.o io.o reset.o switch.o \
elf.o syscall.o signal.o time.o topology.o inst.o ptrace.o vdso.o \
alternative.o unwind.o
obj-y += legacy_boot.o
obj-$(CONFIG_ACPI) += acpi.o
obj-$(CONFIG_EFI) += efi.o

View File

@ -17,6 +17,7 @@
#include <asm/io.h>
#include <asm/numa.h>
#include <asm/loongson.h>
#include "legacy_boot.h"
int acpi_disabled;
EXPORT_SYMBOL(acpi_disabled);
@ -58,7 +59,7 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
}
#ifdef CONFIG_SMP
static int set_processor_mask(u32 id, u32 flags)
int set_processor_mask(u32 id, u32 flags)
{
int cpu, cpuid = id;
@ -132,6 +133,10 @@ static void __init acpi_process_madt(void)
__cpu_logical_map[i] = -1;
}
#endif
if (efi_bp && bpi_version <= BPI_VERSION_V1)
legacy_madt_table_init();
acpi_table_parse_madt(ACPI_MADT_TYPE_CORE_PIC,
acpi_parse_processor, MAX_CORE_PIC);

View File

@ -26,6 +26,7 @@
#include <asm/tlb.h>
#include <asm/loongson.h>
#include <asm/pgalloc.h>
#include "legacy_boot.h"
static unsigned long efi_nr_tables;
static unsigned long efi_config_table;
@ -172,6 +173,9 @@ static int __init set_virtual_map(void)
efi_set_virtual_address_map_t *svam;
efi_memory_desc_t *in, runtime_map[32];
if (efi_bp)
return EFI_SUCCESS;
size = sizeof(efi_memory_desc_t);
for_each_efi_memory_desc(in) {
@ -254,10 +258,12 @@ void __init efi_init(void)
void *config_tables;
struct efi_boot_memmap *tbl;
if (!efi_system_table)
return;
if (efi_system_table)
efi_systab = (efi_system_table_t *)early_memremap_ro(efi_system_table,
sizeof(*efi_systab));
else
efi_systab = (efi_system_table_t *)efi_bp->systemtable;
efi_systab = (efi_system_table_t *)early_memremap_ro(efi_system_table, sizeof(*efi_systab));
if (!efi_systab) {
pr_err("Can't find EFI system table.\n");
return;

View File

@ -12,6 +12,7 @@
#include <asm/bootinfo.h>
#include <asm/loongson.h>
#include <asm/setup.h>
#include "legacy_boot.h"
u64 efi_system_table;
struct loongson_system_configuration loongson_sysconf;
@ -22,6 +23,11 @@ void __init init_environ(void)
int efi_boot = fw_arg0;
char *cmdline = early_memremap_ro(fw_arg1, COMMAND_LINE_SIZE);
legacy_boot_init(fw_arg0, fw_arg1, fw_arg2);
if (efi_bp)
return;
if (efi_boot)
set_bit(EFI_BOOT, &efi.flags);
else

View File

@ -20,6 +20,7 @@
#include <asm/irq.h>
#include <asm/loongson.h>
#include <asm/setup.h>
#include "legacy_boot.h"
DEFINE_PER_CPU(unsigned long, irq_stack);
DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
@ -61,6 +62,12 @@ static int __init early_pci_mcfg_parse(struct acpi_table_header *header)
if (header->length < sizeof(struct acpi_table_mcfg))
return -EINVAL;
for (i = 0; i < MAX_IO_PICS; i++) {
msi_group[i].pci_segment = -1;
msi_group[i].node = -1;
pch_group[i].node = -1;
}
n = (header->length - sizeof(struct acpi_table_mcfg)) /
sizeof(struct acpi_mcfg_allocation);
mcfg = (struct acpi_table_mcfg *)header;
@ -76,14 +83,6 @@ static int __init early_pci_mcfg_parse(struct acpi_table_header *header)
static void __init init_vec_parent_group(void)
{
int i;
for (i = 0; i < MAX_IO_PICS; i++) {
msi_group[i].pci_segment = -1;
msi_group[i].node = -1;
pch_group[i].node = -1;
}
acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse);
}
@ -99,7 +98,7 @@ static int __init get_ipi_irq(void)
void __init init_IRQ(void)
{
int i;
int i, ret;
#ifdef CONFIG_SMP
int r, ipi_irq;
static int ipi_dummy_dev;
@ -111,7 +110,13 @@ void __init init_IRQ(void)
clear_csr_estat(ESTATF_IP);
init_vec_parent_group();
irqchip_init();
if (efi_bp && bpi_version <= BPI_VERSION_V1) {
ret = setup_legacy_IRQ();
if (ret)
panic("IRQ domain init error!\n");
} else {
irqchip_init();
}
#ifdef CONFIG_SMP
ipi_irq = get_ipi_irq();
if (ipi_irq < 0)

View File

@ -0,0 +1,468 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Author: Yun Liu, liuyun@loongson.cn
* Copyright (C) 2020 Loongson Technology Co., Ltd.
*
* This program 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 of the License, or (at your
* option) any later version.
*/
#include <linux/acpi.h>
#include <linux/efi.h>
#include <linux/export.h>
#include <linux/memblock.h>
#include <linux/of_fdt.h>
#include <linux/initrd.h>
#include <asm/early_ioremap.h>
#include <asm/bootinfo.h>
#include <asm/loongson.h>
#include "legacy_boot.h"
#define MAX_CORE_PIC 256
#define PREFIX "ACPI: "
#define MSI_MSG_ADDRESS 0x2FF00000
#define MSI_MSG_DEFAULT_COUNT 0xC0
struct boot_params *efi_bp;
struct loongsonlist_mem_map *g_mmap;
struct acpi_madt_lio_pic *acpi_liointc;
struct acpi_madt_eio_pic *acpi_eiointc[MAX_IO_PICS];
struct acpi_madt_ht_pic *acpi_htintc;
struct acpi_madt_lpc_pic *acpi_pchlpc;
struct acpi_madt_msi_pic *acpi_pchmsi[MAX_IO_PICS];
struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS];
struct irq_domain *cpu_domain;
struct irq_domain *liointc_domain;
struct irq_domain *pch_lpc_domain;
struct irq_domain *pch_msi_domain[MAX_IO_PICS];
struct irq_domain *pch_pic_domain[MAX_IO_PICS];
char arcs_cmdline[COMMAND_LINE_SIZE];
int nr_io_pics;
int bpi_version;
struct acpi_madt_lio_pic liointc_default = {
.address = LOONGSON_REG_BASE + 0x1400,
.size = 256,
.cascade = {2, 3},
.cascade_map = {0x00FFFFFF, 0xff000000},
};
struct acpi_madt_lpc_pic pchlpc_default = {
.address = LS7A_LPC_REG_BASE,
.size = SZ_4K,
.cascade = 19,
};
struct acpi_madt_eio_pic eiointc_default[MAX_IO_PICS];
struct acpi_madt_msi_pic pchmsi_default[MAX_IO_PICS];
struct acpi_madt_bio_pic pchpic_default[MAX_IO_PICS];
static int
acpi_parse_lapic(union acpi_subtable_headers *header, const unsigned long end)
{
struct acpi_madt_local_apic *processor = NULL;
processor = (struct acpi_madt_local_apic *)header;
if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;
acpi_table_print_madt_entry(&header->common);
set_processor_mask(processor->id, processor->lapic_flags);
return 0;
}
static int bad_pch_pic(unsigned long address)
{
if (nr_io_pics >= MAX_IO_PICS) {
pr_warn("WARNING: Max # of I/O PCH_PICs (%d) exceeded (found %d), skipping\n",
MAX_IO_PICS, nr_io_pics);
return 1;
}
if (!address) {
pr_warn("WARNING: Bogus (zero) I/O PCH_PIC address found in table, skipping!\n");
return 1;
}
return 0;
}
void register_default_pic(int id, u32 address, u32 irq_base)
{
int idx, entries;
unsigned long addr;
if (bad_pch_pic(address))
return;
idx = nr_io_pics;
pchpic_default[idx].address = address;
if (idx)
pchpic_default[idx].address |= nid_to_addrbase(id) | HT1LO_OFFSET;
pchpic_default[idx].id = id;
pchpic_default[idx].version = 0;
pchpic_default[idx].size = 0x1000;
pchpic_default[idx].gsi_base = irq_base;
msi_group[nr_io_pics].pci_segment = nr_io_pics;
pch_group[nr_io_pics].node = msi_group[nr_io_pics].node = id;
addr = pchpic_default[idx].address;
/* Read INT_ID.int_num */
entries = (((unsigned long)ls7a_readq(addr) >> 48) & 0xff) + 1;
pchmsi_default[idx].msg_address = MSI_MSG_ADDRESS;
pchmsi_default[idx].start = entries;
pchmsi_default[idx].count = MSI_MSG_DEFAULT_COUNT;
eiointc_default[idx].cascade = 3;
eiointc_default[idx].node = id;
eiointc_default[idx].node_map = 1;
if (idx) {
eiointc_default[idx].cascade = 0x4;
eiointc_default[0].node_map = 0x1DF;
eiointc_default[idx].node_map = 0xFE20;
}
acpi_pchpic[idx] = &pchpic_default[idx];
acpi_pchmsi[idx] = &pchmsi_default[idx];
acpi_eiointc[idx] = &eiointc_default[idx];
nr_io_pics++;
}
static int
acpi_parse_legacy_pch_pic(union acpi_subtable_headers *header, const unsigned long end)
{
struct acpi_madt_io_apic *pch_pic = NULL;
pch_pic = (struct acpi_madt_io_apic *)header;
if (BAD_MADT_ENTRY(pch_pic, end))
return -EINVAL;
acpi_table_print_madt_entry(&header->common);
register_default_pic(pch_pic->id, pch_pic->address,
pch_pic->global_irq_base);
return 0;
}
__init int legacy_madt_table_init(void)
{
/* Parse MADT LAPIC entries */
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, acpi_parse_lapic, MAX_CORE_PIC);
acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_legacy_pch_pic, MAX_IO_PICS);
acpi_liointc = &liointc_default;
acpi_pchlpc = &pchlpc_default;
return 0;
}
int setup_legacy_IRQ(void)
{
int i, ret;
struct irq_domain *pic_domain;
if (!acpi_eiointc[0])
cpu_data[0].options &= ~LOONGARCH_CPU_EXTIOI;
ret = cpuintc_acpi_init(NULL, 0);
if (ret) {
pr_err("CPU domain init error!\n");
return -1;
}
cpu_domain = get_cpudomain();
ret = liointc_acpi_init(cpu_domain, acpi_liointc);
if (ret) {
pr_err("Liointc domain init error!\n");
return -1;
}
liointc_domain = irq_find_matching_fwnode(liointc_handle, DOMAIN_BUS_ANY);
if (cpu_has_extioi) {
pr_info("Using EIOINTC interrupt mode\n");
for (i = 0; i < nr_io_pics; i++) {
ret = eiointc_acpi_init(cpu_domain, acpi_eiointc[i]);
if (ret) {
pr_err("Eiointc domain init error!\n");
return -1;
}
pch_pic_parse_madt((union acpi_subtable_headers *)acpi_pchpic[i], 0);
pch_msi_parse_madt((union acpi_subtable_headers *)acpi_pchmsi[i], 0);
}
/* HTVECINTC maybe not use */
} else {
pr_info("Using HTVECINTC interrupt mode\n");
ret = htvec_acpi_init(liointc_domain, acpi_htintc);
if (ret) {
pr_err("HTVECintc domain init error!\n");
return -1;
}
pch_pic_parse_madt((union acpi_subtable_headers *)acpi_pchpic[0], 0);
pch_msi_parse_madt((union acpi_subtable_headers *)acpi_pchmsi[0], 0);
}
pic_domain = get_pchpic_irq_domain();
if (pic_domain)
pch_lpc_acpi_init(pic_domain, acpi_pchlpc);
return 0;
}
/*
* Manage initrd
*/
#ifdef CONFIG_BLK_DEV_INITRD
static __init int rd_start_early(char *p)
{
phys_initrd_start = __pa(memparse(p, NULL));
return 0;
}
early_param("rd_start", rd_start_early);
static __init int rd_size_early(char *p)
{
phys_initrd_size = memparse(p, NULL);
return 0;
}
early_param("rd_size", rd_size_early);
#endif
__init void fw_init_cmdline(unsigned long argc, unsigned long cmdp)
{
int i;
char **_fw_argv;
_fw_argv = (char **)cmdp;
arcs_cmdline[0] = '\0';
for (i = 1; i < argc; i++) {
strlcat(arcs_cmdline, _fw_argv[i], COMMAND_LINE_SIZE);
if (i < (argc - 1))
strlcat(arcs_cmdline, " ", COMMAND_LINE_SIZE);
}
strscpy(boot_command_line, arcs_cmdline, COMMAND_LINE_SIZE);
}
static u8 ext_listhdr_checksum(u8 *buffer, u32 length)
{
u8 sum = 0;
u8 *end = buffer + length;
while (buffer < end)
sum = (u8)(sum + *(buffer++));
return sum;
}
static int parse_mem(struct _extention_list_hdr *head)
{
g_mmap = (struct loongsonlist_mem_map *)head;
if (ext_listhdr_checksum((u8 *)g_mmap, head->length)) {
pr_err("mem checksum error\n");
return -EPERM;
}
return 0;
}
/* legacy firmware passed, add use this info if need vbios */
static int parse_vbios(struct _extention_list_hdr *head)
{
struct loongsonlist_vbios *pvbios;
pvbios = (struct loongsonlist_vbios *)head;
if (ext_listhdr_checksum((u8 *)pvbios, head->length)) {
pr_err("vbios_addr checksum error\n");
return -EPERM;
}
return 0;
}
/* legacy firmware passed, add use this info if need screeninfo KVM? */
static int parse_screeninfo(struct _extention_list_hdr *head)
{
struct loongsonlist_screeninfo *pscreeninfo;
pscreeninfo = (struct loongsonlist_screeninfo *)head;
if (ext_listhdr_checksum((u8 *)pscreeninfo, head->length)) {
pr_err("screeninfo_addr checksum error\n");
return -EPERM;
}
memcpy(&screen_info, &pscreeninfo->si, sizeof(screen_info));
return 0;
}
static int list_find(struct boot_params *bp)
{
struct _extention_list_hdr *fhead = NULL;
unsigned long index;
fhead = bp->extlist;
if (!fhead) {
pr_err("the bp ext struct empty!\n");
return -1;
}
do {
if (memcmp(&(fhead->signature), LOONGSON_MEM_SIGNATURE, 3) == 0) {
if (parse_mem(fhead) != 0) {
pr_err("parse mem failed\n");
return -EPERM;
}
} else if (memcmp(&(fhead->signature), LOONGSON_VBIOS_SIGNATURE, 5) == 0) {
if (parse_vbios(fhead) != 0) {
pr_err("parse vbios failed\n");
return -EPERM;
}
} else if (memcmp(&(fhead->signature), LOONGSON_SCREENINFO_SIGNATURE, 5) == 0) {
if (parse_screeninfo(fhead) != 0) {
pr_err("parse screeninfo failed\n");
return -EPERM;
}
}
fhead = (struct _extention_list_hdr *)fhead->next;
index = (unsigned long)fhead;
} while (index);
return 0;
}
unsigned int bpi_init(void)
{
return list_find(efi_bp);
}
static int get_bpi_version(u64 *signature)
{
u8 data[9];
int version = BPI_VERSION_NONE;
data[8] = 0;
memcpy(data, signature, sizeof(*signature));
if (kstrtoint(&data[3], 10, &version))
return BPI_VERSION_NONE;
return version;
}
static void __init parse_bpi_flags(void)
{
if (efi_bp->flags & BPI_FLAGS_UEFI_SUPPORTED)
set_bit(EFI_BOOT, &efi.flags);
else
clear_bit(EFI_BOOT, &efi.flags);
}
__init unsigned long legacy_boot_init(unsigned long argc, unsigned long cmdptr, unsigned long bpi)
{
int ret;
if (!bpi || argc < 2)
return -1;
efi_bp = (struct boot_params *)bpi;
bpi_version = get_bpi_version(&efi_bp->signature);
pr_info("BPI%d with boot flags %llx.\n", bpi_version, efi_bp->flags);
if (bpi_version == BPI_VERSION_NONE)
panic("Fatal error, bpi ver BONE!\n");
else if (bpi_version == BPI_VERSION_V2)
parse_bpi_flags();
fw_init_cmdline(argc, cmdptr);
ret = bpi_init();
if (ret) {
pr_err("init legacy firmware error!\n");
return -1;
}
return 0;
}
static int __init add_legacy_isa_io(struct fwnode_handle *fwnode, unsigned long isa_base)
{
int ret = 0;
unsigned long vaddr;
struct logic_pio_hwaddr *range;
range = kzalloc(sizeof(*range), GFP_ATOMIC);
if (!range)
return -ENOMEM;
range->fwnode = fwnode;
range->size = ISA_IOSIZE;
range->hw_start = isa_base;
range->flags = LOGIC_PIO_CPU_MMIO;
ret = logic_pio_register_range(range);
if (ret) {
kfree(range);
return ret;
}
if (range->io_start != 0) {
logic_pio_unregister_range(range);
kfree(range);
return -EINVAL;
}
vaddr = (unsigned long)(PCI_IOBASE + range->io_start);
ret = ioremap_page_range(vaddr, vaddr + range->size, range->hw_start,
pgprot_device(PAGE_KERNEL));
return ret;
}
static struct fwnode_handle * __init parse_isa_base(u64 *cpu_addr)
{
struct device_node *np;
const __be32 *ranges = NULL;
int len;
struct device_node *node;
for_each_node_by_name(np, "isa") {
node = of_node_get(np);
if (!node)
break;
ranges = of_get_property(node, "ranges", &len);
if (!ranges || (ranges && len > 0))
break;
}
if (ranges) {
ranges += 2;
*cpu_addr = of_translate_address(np, ranges);
return &np->fwnode;
}
return NULL;
}
static int __init register_legacy_isa_io(void)
{
struct fwnode_handle *fwnode;
u64 cpu_addr;
if (!acpi_disabled) {
cpu_addr = ISA_PHY_IOBASE;
fwnode = kzalloc(sizeof(*fwnode), GFP_ATOMIC);
} else {
fwnode = parse_isa_base(&cpu_addr);
}
if (fwnode)
add_legacy_isa_io(fwnode, cpu_addr);
return 0;
}
arch_initcall(register_legacy_isa_io);

View File

@ -0,0 +1,90 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LEGACY_BOOT_H_
#define __LEGACY_BOOT_H_
#include <linux/screen_info.h>
#include <linux/of_address.h>
#define ADDRESS_TYPE_SYSRAM 1
#define ADDRESS_TYPE_RESERVED 2
#define ADDRESS_TYPE_ACPI 3
#define ADDRESS_TYPE_NVS 4
#define ADDRESS_TYPE_PMEM 5
#define LOONGSON3_BOOT_MEM_MAP_MAX 128
#define RT_MAP_START 100
#define FIX_MAP_ENTRY 32
/* mask of the flags in bootparamsinterface */
#define BPI_FLAGS_UEFI_SUPPORTED BIT(0)
#define BPI_FLAGS_SOC_CPU BIT(1)
#define LOONGSON_DMA_MASK_BIT 64
#define LOONGSON_MEM_SIGNATURE "MEM"
#define LOONGSON_VBIOS_SIGNATURE "VBIOS"
#define LOONGSON_EFIBOOT_SIGNATURE "BPI"
#define LOONGSON_SCREENINFO_SIGNATURE "SINFO"
#define LOONGSON_EFIBOOT_VERSION 1000
/* Values for Version firmware */
enum bpi_vers {
BPI_VERSION_NONE = 0,
BPI_VERSION_V1 = 1000,
BPI_VERSION_V2 = 1001,
};
struct boot_params {
u64 signature; /* {"BPIXXXXX"} */
void *systemtable;
struct _extention_list_hdr *extlist;
u64 flags;
} __packed;
struct _extention_list_hdr {
u64 signature;
u32 length;
u8 revision;
u8 checksum;
struct _extention_list_hdr *next;
} __packed;
struct loongsonlist_mem_map {
struct _extention_list_hdr header; /*{"M", "E", "M"}*/
u8 map_count;
struct _loongson_mem_map {
u32 mem_type;
u64 mem_start;
u64 mem_size;
} __packed map[LOONGSON3_BOOT_MEM_MAP_MAX];
} __packed;
struct loongsonlist_vbios {
struct _extention_list_hdr header; /* {VBIOS} */
u64 vbios_addr;
} __packed;
struct loongsonlist_screeninfo {
struct _extention_list_hdr header;
struct screen_info si;
};
unsigned long legacy_boot_init(unsigned long argc,
unsigned long cmdptr, unsigned long bpi);
extern int bpi_version;
extern struct boot_params *efi_bp;
extern struct loongsonlist_mem_map *g_mmap;
extern int set_processor_mask(u32 id, u32 flags);
extern int __init setup_legacy_IRQ(void);
extern struct loongson_system_configuration loongson_sysconf;
extern unsigned long long smp_group[MAX_PACKAGES];
extern int legacy_madt_table_init(void);
extern struct pch_pic *pch_pic_priv[MAX_IO_PICS];
extern struct irq_domain *get_cpudomain(void);
extern int __init cpuintc_acpi_init(union acpi_subtable_headers *header,
const unsigned long end);
extern int __init
pch_pic_parse_madt(union acpi_subtable_headers *header,
const unsigned long end);
extern int __init
pch_msi_parse_madt(union acpi_subtable_headers *header,
const unsigned long end);
extern struct irq_domain *get_pchpic_irq_domain(void);
#endif

View File

@ -9,13 +9,36 @@
#include <asm/bootinfo.h>
#include <asm/loongson.h>
#include <asm/sections.h>
#include "legacy_boot.h"
void __init memblock_init(void)
{
u32 mem_type;
u32 i, mem_type;
u64 mem_start, mem_end, mem_size;
efi_memory_desc_t *md;
if (g_mmap) {
/* parse memory information */
for (i = 0; i < g_mmap->map_count; i++) {
mem_type = g_mmap->map[i].mem_type;
mem_start = g_mmap->map[i].mem_start;
mem_size = g_mmap->map[i].mem_size;
mem_end = mem_start + mem_size;
switch (mem_type) {
case ADDRESS_TYPE_SYSRAM:
pr_info("add memory region memblock - base: 0x%llx size: 0x%llx\n",
mem_start, mem_size);
memblock_add(mem_start, mem_size);
if (max_low_pfn < (mem_end >> PAGE_SHIFT))
max_low_pfn = mem_end >> PAGE_SHIFT;
break;
}
}
memblock_set_current_limit(PFN_PHYS(max_low_pfn));
memblock_reserve(__pa_symbol(&_text),
__pa_symbol(&_end) - __pa_symbol(&_text));
return;
}
/* Parse memory information */
for_each_efi_memory_desc(md) {
mem_type = md->type;

View File

@ -25,6 +25,7 @@
#include <asm/pgalloc.h>
#include <asm/sections.h>
#include <asm/time.h>
#include "legacy_boot.h"
int numa_off;
struct pglist_data *node_data[MAX_NUMNODES];
@ -37,7 +38,6 @@ static struct numa_meminfo numa_meminfo;
cpumask_t cpus_on_node[MAX_NUMNODES];
cpumask_t phys_cpus_on_node[MAX_NUMNODES];
EXPORT_SYMBOL(cpus_on_node);
/*
* apicid, cpu, node mappings
*/
@ -301,10 +301,45 @@ static void __init add_numamem_region(u64 start, u64 end, u32 type)
static void __init init_node_memblock(void)
{
u32 mem_type;
u32 i, mem_type;
u64 mem_end, mem_start, mem_size;
efi_memory_desc_t *md;
if (g_mmap) {
for (i = 0; i < g_mmap->map_count; i++) {
mem_type = g_mmap->map[i].mem_type;
mem_start = g_mmap->map[i].mem_start;
mem_size = g_mmap->map[i].mem_size;
mem_end = g_mmap->map[i].mem_start + mem_size;
switch (mem_type) {
case ADDRESS_TYPE_SYSRAM:
mem_start = PFN_ALIGN(mem_start);
mem_end = PFN_ALIGN(mem_end - PAGE_SIZE + 1);
if (mem_start >= mem_end)
break;
add_numamem_region(mem_start, mem_end, EFI_PERSISTENT_MEMORY);
break;
case ADDRESS_TYPE_ACPI:
mem_start = PFN_ALIGN(mem_start - PAGE_SIZE + 1);
mem_end = PFN_ALIGN(mem_end);
mem_size = mem_end - mem_start;
memblock_add(mem_start, mem_size);
memblock_mark_nomap(mem_start, mem_size);
memblock_set_node(mem_start, mem_size,
&memblock.memory, 0);
memblock_reserve(mem_start, mem_size);
break;
case ADDRESS_TYPE_RESERVED:
memblock_reserve(mem_start, mem_size);
break;
}
}
return;
}
/* Parse memory information and activate */
for_each_efi_memory_desc(md) {
mem_type = md->type;

View File

@ -49,7 +49,8 @@ void machine_power_off(void)
#endif
do_kernel_power_off();
#ifdef CONFIG_EFI
efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
if (efi.reset_system)
efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
#endif
while (true) {

View File

@ -48,6 +48,7 @@
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/time.h>
#include "legacy_boot.h"
#define SMBIOS_BIOSSIZE_OFFSET 0x09
#define SMBIOS_BIOSEXTERN_OFFSET 0x13
@ -134,9 +135,23 @@ static void __init parse_cpu_table(const struct dmi_header *dm)
static void __init parse_bios_table(const struct dmi_header *dm)
{
int bios_extern;
char *dmi_data = (char *)dm;
bios_extern = *(dmi_data + SMBIOS_BIOSEXTERN_OFFSET);
b_info.bios_size = (*(dmi_data + SMBIOS_BIOSSIZE_OFFSET) + 1) << 6;
if (bpi_version == BPI_VERSION_V2) {
if ((!!(efi_bp->flags & BPI_FLAGS_UEFI_SUPPORTED))
!= (!!(bios_extern & LOONGSON_EFI_ENABLE)))
pr_err("There is a conflict of definitions between efi_bp->flags and smbios\n");
return;
}
if (bios_extern & LOONGSON_EFI_ENABLE)
set_bit(EFI_BOOT, &efi.flags);
else
clear_bit(EFI_BOOT, &efi.flags);
}
static void __init find_tokens(const struct dmi_header *dm, void *dummy)
@ -614,7 +629,9 @@ void __init setup_arch(char **cmdline_p)
pagetable_init();
bootcmdline_init(cmdline_p);
parse_early_param();
reserve_initrd_mem();
/* The small fdt method should be skipped directly to avoid two reserved operations. */
if (fw_arg2)
reserve_initrd_mem();
platform_init();
arch_mem_init(cmdline_p);

View File

@ -32,6 +32,7 @@
#include <asm/processor.h>
#include <asm/setup.h>
#include <asm/time.h>
#include "legacy_boot.h"
int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
EXPORT_SYMBOL(__cpu_number_map);
@ -310,11 +311,12 @@ void __init loongson_prepare_cpus(unsigned int max_cpus)
*/
void loongson_boot_secondary(int cpu, struct task_struct *idle)
{
unsigned long entry;
unsigned long entry = (unsigned long)&smpboot_entry;
pr_info("Booting CPU#%d...\n", cpu);
entry = __pa_symbol((unsigned long)&smpboot_entry);
if (!efi_bp)
entry = __pa_symbol((unsigned long)&smpboot_entry);
cpuboot_data.stack = (unsigned long)__KSTK_TOS(idle);
cpuboot_data.thread_info = (unsigned long)task_thread_info(idle);

View File

@ -58,13 +58,159 @@ static void acpi_release_root_info(struct acpi_pci_root_info *ci)
kfree(info);
}
static void arch_pci_root_validate_resources(struct device *dev,
struct list_head *resources,
unsigned long type)
{
LIST_HEAD(list);
struct resource *res1, *res2, *root = NULL;
struct resource_entry *tmp, *entry, *entry2;
WARN_ON((type & (IORESOURCE_MEM | IORESOURCE_IO)) == 0);
root = (type & IORESOURCE_MEM) ? &iomem_resource : &ioport_resource;
list_splice_init(resources, &list);
resource_list_for_each_entry_safe(entry, tmp, &list) {
bool free = false;
resource_size_t end;
res1 = entry->res;
if (!(res1->flags & type))
goto next;
/* Exclude non-addressable range or non-addressable portion */
end = min(res1->end, root->end);
if (end <= res1->start) {
dev_info(dev, "host bridge window %pR (ignored, not CPU addressable)\n",
res1);
free = true;
goto next;
} else if (res1->end != end) {
dev_info(dev, "host bridge window %pR ([%#llx-%#llx] ignored, not CPU addressable)\n",
res1, (unsigned long long)end + 1,
(unsigned long long)res1->end);
res1->end = end;
}
resource_list_for_each_entry(entry2, resources) {
res2 = entry2->res;
if (!(res2->flags & type))
continue;
/*
* I don't like throwing away windows because then
* our resources no longer match the ACPI _CRS, but
* the kernel resource tree doesn't allow overlaps.
*/
if (resource_overlaps(res1, res2)) {
res2->start = min(res1->start, res2->start);
res2->end = max(res1->end, res2->end);
dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
res2, res1);
free = true;
goto next;
}
}
next:
resource_list_del(entry);
if (free)
resource_list_free_entry(entry);
else
resource_list_add_tail(entry, resources);
}
}
static void arch_pci_root_remap_iospace(struct fwnode_handle *fwnode,
struct resource_entry *entry)
{
struct resource *res = entry->res;
resource_size_t cpu_addr = res->start;
resource_size_t pci_addr = cpu_addr - entry->offset;
resource_size_t length = resource_size(res);
unsigned long port;
if (pci_register_io_range(fwnode, cpu_addr, length)) {
res->start += ISA_IOSIZE;
cpu_addr = res->start;
pci_addr = cpu_addr - entry->offset;
length = resource_size(res);
if (pci_register_io_range(fwnode, cpu_addr, length))
goto err;
}
port = pci_address_to_pio(cpu_addr);
if (port == (unsigned long)-1)
goto err;
res->start = port;
res->end = port + length - 1;
entry->offset = port - pci_addr;
if (pci_remap_iospace(res, cpu_addr) < 0)
goto err;
pr_info("Remapped I/O %pa to %pR\n", &cpu_addr, res);
return;
err:
res->flags |= IORESOURCE_DISABLED;
}
static int arch_pci_probe_root_resources(struct acpi_pci_root_info *info)
{
int ret;
struct list_head *list = &info->resources;
struct acpi_device *device = info->bridge;
struct resource_entry *entry, *tmp;
unsigned long flags;
struct resource *res;
flags = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT;
ret = acpi_dev_get_resources(device, list,
acpi_dev_filter_resource_type_cb,
(void *)flags);
if (ret < 0)
dev_warn(&device->dev,
"failed to parse _CRS method, error code %d\n", ret);
else if (ret == 0)
dev_dbg(&device->dev,
"no IO and memory resources present in _CRS\n");
else {
resource_list_for_each_entry_safe(entry, tmp, list) {
if (entry->res->flags & IORESOURCE_IO) {
res = entry->res;
res->start = PFN_ALIGN(res->start);
res->end += 1;
res->end = PFN_ALIGN(res->end);
res->end -= 1;
if (!entry->offset) {
entry->offset = LOONGSON_LIO_BASE;
res->start |= LOONGSON_LIO_BASE;
res->end |= LOONGSON_LIO_BASE;
}
arch_pci_root_remap_iospace(&device->fwnode,
entry);
}
if (entry->res->flags & IORESOURCE_DISABLED)
resource_list_destroy_entry(entry);
else
entry->res->name = info->name;
}
arch_pci_root_validate_resources(&device->dev, list,
IORESOURCE_MEM);
arch_pci_root_validate_resources(&device->dev, list,
IORESOURCE_IO);
}
return ret;
}
static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci)
{
int status;
struct resource_entry *entry, *tmp;
struct acpi_device *device = ci->bridge;
status = acpi_pci_probe_root_resources(ci);
status = arch_pci_probe_root_resources(ci);
if (status > 0) {
resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
if (entry->res->flags & IORESOURCE_MEM) {

View File

@ -37,6 +37,7 @@ obj-$(CONFIG_ARM) += $(arm-obj-y)
obj-$(CONFIG_ARM64) += $(arm-obj-y)
riscv-obj-$(CONFIG_EFI) := efi-init.o riscv-runtime.o
obj-$(CONFIG_RISCV) += $(riscv-obj-y)
#obj-$(CONFIG_LOONGARCH) += efi-init.o
obj-$(CONFIG_EFI_CAPSULE_LOADER) += capsule-loader.o
obj-$(CONFIG_EFI_EARLYCON) += earlycon.o
obj-$(CONFIG_UEFI_CPER_ARM) += cper-arm.o

View File

@ -141,7 +141,12 @@ static int __init acpi_cascade_irqdomain_init(void)
return 0;
}
static int __init cpuintc_acpi_init(union acpi_subtable_headers *header,
struct irq_domain *get_cpudomain(void)
{
return irq_domain;
}
int __init cpuintc_acpi_init(union acpi_subtable_headers *header,
const unsigned long end)
{
int ret;

View File

@ -328,7 +328,7 @@ static struct syscore_ops eiointc_syscore_ops = {
.resume = eiointc_resume,
};
static int __init pch_pic_parse_madt(union acpi_subtable_headers *header,
int __init pch_pic_parse_madt(union acpi_subtable_headers *header,
const unsigned long end)
{
struct acpi_madt_bio_pic *pchpic_entry = (struct acpi_madt_bio_pic *)header;
@ -341,7 +341,7 @@ static int __init pch_pic_parse_madt(union acpi_subtable_headers *header,
return 0;
}
static int __init pch_msi_parse_madt(union acpi_subtable_headers *header,
int __init pch_msi_parse_madt(union acpi_subtable_headers *header,
const unsigned long end)
{
struct irq_domain *parent;

View File

@ -52,6 +52,11 @@ static struct pch_pic *pch_pic_priv[MAX_IO_PICS];
struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];
struct irq_domain *get_pchpic_irq_domain(void)
{
return pch_pic_priv[0]->pic_domain;
}
static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit)
{
u32 reg;