未验证 提交 3e5cc39a 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!476 LoongArch: fix failed to boot

Merge Pull Request from: @Hongchen_Zhang 
 
1. commit ad404010 ("entry: Add support for TIF_NOTIFY_SIGNAL")
changed the signal handler name to arch_do_signal_or_restart,so
change the signal handler name for LoongArch too.
2. fix virtual machine startup error
3. fix failed boot when using old firmware 

After apply this PR,the following test case passed:
  - boot Loongson-3C5000LL+7A1000 machine with firmware
     Loongson-UDK2018-V2.0.04163-beta6
  - success boot to login
 
 
Link:https://gitee.com/openeuler/kernel/pulls/476 

Reviewed-by: Guo Dongtai <guodongtai@kylinos.cn> 
Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> 
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> 
......@@ -53,6 +53,7 @@ struct acpi_vector_group {
extern struct acpi_vector_group pch_group[MAX_IO_PICS];
extern struct acpi_vector_group msi_group[MAX_IO_PICS];
#define MAX_CORES_PER_EIO_NODE 256
#define CORES_PER_EIO_NODE 4
#define LOONGSON_CPU_UART0_VEC 10 /* CPU UART0 */
......
......@@ -275,6 +275,11 @@ static __always_inline u64 iocsr_read64(u32 reg)
return __iocsrrd_d(reg);
}
static __always_inline void iocsr_write8(u8 val, u32 reg)
{
__iocsrwr_b(val, reg);
}
static __always_inline void iocsr_write32(u32 val, u32 reg)
{
__iocsrwr_w(val, reg);
......
......@@ -28,6 +28,7 @@
#include <asm/loongson.h>
#include "legacy_boot.h"
static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
static __initdata unsigned long new_memmap = EFI_INVALID_TABLE_ADDR;
static __initdata unsigned long initrd = EFI_INVALID_TABLE_ADDR;
......@@ -36,12 +37,32 @@ static unsigned long efi_config_table;
static efi_system_table_t *efi_systab;
static efi_config_table_type_t arch_tables[] __initdata = {
{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table, NULL},
{LINUX_EFI_NEW_MEMMAP_GUID, &new_memmap, "NEWMEM"},
{LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD"},
{},
};
static __initdata pgd_t *pgd_efi;
static void __init init_screen_info(void)
{
struct screen_info *si;
if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
si = early_memremap_ro(screen_info_table, sizeof(*si));
if (!si) {
pr_err("Could not map screen_info config table\n");
return;
}
screen_info = *si;
memset(si, 0, sizeof(*si));
early_memunmap(si, sizeof(*si));
}
if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI)
memblock_reserve(screen_info.lfb_base, screen_info.lfb_size);
}
static int __init efimap_populate_hugepages(
unsigned long start, unsigned long end,
pgprot_t prot)
......@@ -290,6 +311,5 @@ void __init loongson_efi_init(void)
init_new_memmap();
if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI)
memblock_reserve(screen_info.lfb_base, screen_info.lfb_size);
init_screen_info();
}
......@@ -113,13 +113,15 @@ static int bad_pch_pic(unsigned long address)
void register_default_pic(int id, u32 address, u32 irq_base)
{
int idx, entries;
int j, idx, entries, cores;
unsigned long addr;
u64 node_map = 0;
if (bad_pch_pic(address))
return;
idx = nr_io_pics;
cores = (cpu_has_hypervisor ? MAX_CORES_PER_EIO_NODE : CORES_PER_EIO_NODE);
pchpic_default[idx].address = address;
if (idx)
......@@ -138,14 +140,27 @@ void register_default_pic(int id, u32 address, u32 irq_base)
pchmsi_default[idx].start = entries;
pchmsi_default[idx].count = MSI_MSG_DEFAULT_COUNT;
eiointc_default[idx].cascade = 3;
for_each_possible_cpu(j) {
int node = cpu_logical_map(j) / cores;
node_map |= (1 << node);
}
eiointc_default[idx].cascade = 3 + idx;
eiointc_default[idx].node = id;
eiointc_default[idx].node_map = 1;
eiointc_default[idx].node_map = node_map;
if (idx) {
eiointc_default[idx].cascade = 0x4;
eiointc_default[0].node_map = 0x1DF;
eiointc_default[idx].node_map = 0xFE20;
int i;
for (i = 0; i < idx + 1; i++) {
node_map = 0;
for_each_possible_cpu(j) {
int node = cpu_logical_map(j) / cores;
if (((node & 7) < 4) ? !i : i)
node_map |= (1 << node);
}
eiointc_default[i].node_map = node_map;
}
}
acpi_pchpic[idx] = &pchpic_default[idx];
......@@ -278,7 +293,7 @@ int setup_legacy_IRQ(void)
printk("Pic domain error!\n");
return -1;
}
if (pic_domain)
if (pic_domain && !cpu_has_hypervisor)
pch_lpc_acpi_init(pic_domain, acpi_pchlpc);
return 0;
......@@ -530,9 +545,12 @@ unsigned long legacy_boot_init(unsigned long argc, unsigned long cmdptr, unsigne
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)
if (bpi_version == BPI_VERSION_NONE) {
if (cpu_has_hypervisor)
pr_err("Fatal error, bpi ver BONE!\n");
else
panic("Fatal error, bpi ver BONE!\n");
} else if (bpi_version == BPI_VERSION_V2)
parse_bpi_flags();
fw_init_cmdline(argc, cmdptr);
......
......@@ -853,11 +853,11 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
signal_setup_done(ret, ksig, 0);
}
void arch_do_signal(struct pt_regs *regs)
void arch_do_signal_or_restart(struct pt_regs *regs, bool has_signal)
{
struct ksignal ksig;
if (get_signal(&ksig)) {
if (has_signal && get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */
handle_signal(&ksig, regs);
return;
......
......@@ -139,11 +139,13 @@ static int ls7a_ioapic_reg_write(struct ls7a_kvm_ioapic *s,
struct kvm_ls7a_ioapic_state *state;
int64_t offset_tmp;
uint64_t offset;
uint64_t data, old;
uint64_t data, old, himask, lowmask;;
offset = addr & 0xfff;
kvm = s->kvm;
state = &(s->ls7a_ioapic);
lowmask = 0xFFFFFFFFUL;
himask = lowmask << 32;
if (offset & (len - 1)) {
printk("%s(%d):unaligned address access %llx size %d \n",
......@@ -191,6 +193,80 @@ static int ls7a_ioapic_reg_write(struct ls7a_kvm_ioapic *s,
WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len);
break;
}
} else if (4 == len) {
data = *(uint32_t *)val;
switch (offset) {
case LS7A_INT_MASK_OFFSET:
old = state->int_mask & lowmask;
state->int_mask = (state->int_mask & himask) | data;
if (old & ~data)
kvm_ls7a_ioapic_raise(kvm, old & ~data);
if (~old & data)
kvm_ls7a_ioapic_lower(kvm, ~old & data);
break;
case LS7A_INT_MASK_OFFSET + 4:
data = data << 32;
old = state->int_mask & himask;
state->int_mask = (state->int_mask & lowmask) | data;
if (old & ~data)
kvm_ls7a_ioapic_raise(kvm, old & ~data);
if (~old & data)
kvm_ls7a_ioapic_lower(kvm, ~old & data);
break;
case LS7A_INT_STATUS_OFFSET:
state->intisr = (state->intisr & himask) | data;
break;
case LS7A_INT_STATUS_OFFSET + 4:
data = data << 32;
state->intisr = (state->intisr & lowmask) | data;
break;
case LS7A_INT_EDGE_OFFSET:
state->intedge = (state->intedge & himask) | data;
break;
case LS7A_INT_EDGE_OFFSET + 4:
data = data << 32;
state->intedge = (state->intedge & lowmask) | data;
break;
case LS7A_INT_CLEAR_OFFSET:
/*
* only clear edge triggered irq on writing INTCLR reg
* no effect on level triggered irq
*/
data = data & state->intedge;
state->intirr &= ~data;
kvm_ls7a_ioapic_lower(kvm, data);
state->intisr &= ~data;
break;
case LS7A_INT_CLEAR_OFFSET + 4:
data = data << 32;
data = data & state->intedge;
state->intirr &= ~data;
kvm_ls7a_ioapic_lower(kvm, data);
state->intisr &= ~data;
break;
case LS7A_INT_POL_OFFSET:
state->int_polarity = (state->int_polarity & himask) | data;
break;
case LS7A_INT_POL_OFFSET+4:
data = data << 32;
state->int_polarity = (state->int_polarity & lowmask) | data;
break;
case LS7A_HTMSI_EN_OFFSET:
state->htmsi_en = (state->htmsi_en & himask) | data;
break;
case LS7A_HTMSI_EN_OFFSET+4:
data = data << 32;
state->htmsi_en = (state->htmsi_en & lowmask) | data;
break;
case LS7A_AUTO_CTRL0_OFFSET:
case LS7A_AUTO_CTRL0_OFFSET+4:
case LS7A_AUTO_CTRL1_OFFSET:
case LS7A_AUTO_CTRL1_OFFSET+4:
break;
default:
WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len);
break;
}
} else if (1 == len) {
data = *(unsigned char *)val;
if (offset >= LS7A_HTMSI_VEC_OFFSET) {
......@@ -240,11 +316,13 @@ static int ls7a_ioapic_reg_read(struct ls7a_kvm_ioapic *s,
uint64_t offset, offset_tmp;
struct kvm *kvm;
struct kvm_ls7a_ioapic_state *state;
uint64_t result = 0;
uint64_t result = 0, lowmask, himask;
state = &(s->ls7a_ioapic);
kvm = s->kvm;
offset = addr & 0xfff;
lowmask = 0xFFFFFFFFUL;
himask = lowmask << 32;
if (offset & (len - 1)) {
printk("%s(%d):unaligned address access %llx size %d \n",
__FUNCTION__, __LINE__, addr, len);
......@@ -281,6 +359,60 @@ static int ls7a_ioapic_reg_read(struct ls7a_kvm_ioapic *s,
}
if (val != NULL)
*(uint64_t *)val = result;
} else if (4 == len) {
switch (offset) {
case LS7A_INT_MASK_OFFSET:
result = state->int_mask & lowmask;
break;
case LS7A_INT_MASK_OFFSET + 4:
result = state->int_mask & himask;
result = result >> 32;
break;
case LS7A_INT_STATUS_OFFSET:
result = state->intisr & (~state->int_mask) & lowmask;
break;
case LS7A_INT_STATUS_OFFSET + 4:
result = state->intisr & (~state->int_mask) & himask;
result = result >> 32;
break;
case LS7A_INT_EDGE_OFFSET:
result = state->intedge & lowmask;
break;
case LS7A_INT_EDGE_OFFSET + 4:
result = state->intedge & himask;
result = result >> 32;
break;
case LS7A_INT_POL_OFFSET:
result = state->int_polarity & lowmask;
break;
case LS7A_INT_POL_OFFSET + 4:
result = state->int_polarity & himask;
result = result >> 32;
break;
case LS7A_HTMSI_EN_OFFSET:
result = state->htmsi_en & lowmask;
break;
case LS7A_HTMSI_EN_OFFSET + 4:
result = state->htmsi_en & himask;
result = result >> 32;
break;
case LS7A_AUTO_CTRL0_OFFSET:
case LS7A_AUTO_CTRL0_OFFSET + 4:
case LS7A_AUTO_CTRL1_OFFSET:
case LS7A_AUTO_CTRL1_OFFSET + 4:
break;
case LS7A_INT_ID_OFFSET:
result = LS7A_INT_ID_VAL;
break;
case LS7A_INT_ID_OFFSET + 4:
result = LS7A_INT_ID_VER;
break;
default:
WARN_ONCE(1, "Abnormal address access:addr 0x%llx,len %d\n", addr, len);
break;
}
if (val != NULL)
*(uint32_t *)val = result;
} else if (1 == len) {
if (offset >= LS7A_HTMSI_VEC_OFFSET) {
offset_tmp = offset - LS7A_HTMSI_VEC_OFFSET;
......
......@@ -58,7 +58,9 @@ static void eiointc_enable(void)
static int cpu_to_eio_node(int cpu)
{
return cpu_logical_map(cpu) / CORES_PER_EIO_NODE;
int cores = (cpu_has_hypervisor ? MAX_CORES_PER_EIO_NODE : CORES_PER_EIO_NODE);
return cpu_logical_map(cpu) / cores;
}
static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int mnode, nodemask_t *node_map)
......@@ -89,6 +91,11 @@ static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int mnode,
static DEFINE_RAW_SPINLOCK(affinity_lock);
static void virt_extioi_set_irq_route(int irq, unsigned int cpu)
{
iocsr_write8(cpu_logical_map(cpu), EIOINTC_REG_ROUTE + irq);
}
static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, bool force)
{
unsigned int cpu;
......@@ -111,16 +118,22 @@ static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *af
vector = d->hwirq;
regaddr = EIOINTC_REG_ENABLE + ((vector >> 5) << 2);
/* Mask target vector */
csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)),
0x0, priv->node * CORES_PER_EIO_NODE);
/* Set route for target vector */
eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map);
/* Unmask target vector */
csr_any_send(regaddr, EIOINTC_ALL_ENABLE,
0x0, priv->node * CORES_PER_EIO_NODE);
if (cpu_has_hypervisor) {
iocsr_write32(EIOINTC_ALL_ENABLE & ~BIT(vector & 0x1F), regaddr);
virt_extioi_set_irq_route(vector, cpu);
iocsr_write32(EIOINTC_ALL_ENABLE, regaddr);
} else {
/* Mask target vector */
csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)),
0x0, priv->node * CORES_PER_EIO_NODE);
/* Set route for target vector */
eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map);
/* Unmask target vector */
csr_any_send(regaddr, EIOINTC_ALL_ENABLE,
0x0, priv->node * CORES_PER_EIO_NODE);
}
irq_data_update_effective_affinity(d, cpumask_of(cpu));
......@@ -146,14 +159,15 @@ static int eiointc_router_init(unsigned int cpu)
int i, bit;
uint32_t data;
uint32_t node = cpu_to_eio_node(cpu);
uint32_t index = eiointc_index(node);
int index = eiointc_index(node);
int cores = (cpu_has_hypervisor ? MAX_CORES_PER_EIO_NODE : CORES_PER_EIO_NODE);
if (index < 0) {
pr_err("Error: invalid nodemap!\n");
return -1;
}
if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) {
if ((cpu_logical_map(cpu) % cores) == 0) {
eiointc_enable();
for (i = 0; i < VEC_COUNT / 32; i++) {
......@@ -170,7 +184,7 @@ static int eiointc_router_init(unsigned int cpu)
for (i = 0; i < VEC_COUNT / 4; i++) {
/* Route to Node-0 Core-0 */
if (index == 0)
bit = BIT(cpu_logical_map(0));
bit = (cpu_has_hypervisor ? cpu_logical_map(0) : BIT(cpu_logical_map(0)));
else
bit = (eiointc_priv[index]->node << 4) | 1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册