Trap divide error

Hi, I have a kernel I'm trying to run on a U280 XRT fails to load it with the following dmesg: [448317.846952] xocl 0000:a4:00.1: p2p.u.10485761 ffff8e8914708410 p2p_bar_map: bank addr ffffffff...

Hi,

I have a kernel I’m trying to run on a U280

XRT fails to load it with the following dmesg:

[448317.846952] xocl 0000:a4:00.1: p2p.u.10485761 ffff8e8914708410 p2p_bar_map: bank addr ffffffffffffffff, sz 0, slots 1
[448317.846955] xocl 0000:a4:00.1: p2p.u.10485761 ffff8e8914708410 p2p_bar_map: mark 1 - 0 chunks
[448317.846963] xocl 0000:a4:00.1:  ffff8e895767a0a0 xocl_init_mem: drm_mm_init called for the available memory range
[448317.846965] xocl 0000:a4:00.1:  ffff8e895767a0a0 xocl_init_mem: ret 0
[448317.846974] xocl 0000:a4:00.1:  ffff8e895767a0a0 xocl_read_axlf_helper: Loaded xclbin c5e56ff2-d992-4276-90e3-1fe378964cc2
[448317.851986] traps: python[2077] trap divide error ip:7fd8916ad2cb sp:7ffd3ccab770 error:0 in libxrt_coreutil.so.2.8.743[7fd891664000+c7000]
[448318.310748] [drm] client exits pid(2077)
[448318.310753] xocl 0000:a4:00.1:  ffff8e895767a0a0 xocl_drvinst_close: CLOSE 3

2 kernels are in the XCLBIN as folows. I suspect XRT doesn’t like partiitoned arrays on AXILITE

void read_pointer_sum1(word_t* pin, int nread, int nzero[N], int csum[N])
{
#pragma HLS INTERFACE ap_memory port=nzero
#pragma HLS INTERFACE ap_memory port=csum

#pragma HLS INTERFACE m_axi port=pin offset=slave bundle=gmem0

	int thesum  = 0;
	for(int i = 0; i < nread; i++) {
		#pragma HLS PIPELINE II=1
		word_t in = pin[i];
		nzero[i] = in.countLeadingZeros();
		int input = in.range(31, 0).to_int();
		thesum += input;
		csum[i] = thesum;
		for(int w = 0; w < NINT; w++) {
			int v = in.range((w+1)*sizeof(int)*8-1, w*sizeof(int)*8).to_int();
		}

	}
}

void read_pointer_sum2(word_t* pin, int nread, int nzero[N], int csum[N])
{
#pragma HLS INTERFACE ap_memory port=nzero
#pragma HLS INTERFACE ap_memory port=csum

#pragma HLS INTERFACE m_axi port=pin offset=slave bundle=gmem0
#pragma HLS ARRAY_PARTITION variable=csum cyclic factor=NINT
	int thesum  = 0;
	for(int i = 0; i < nread; i++) {
		//#pragma HLS PIPELINE II=1
		word_t in = pin[i];
		nzero[i] = in.countLeadingZeros();
		int input = in.range(31, 0).to_int();
		thesum += input;
		for(int w = 0; w < NINT; w++) {
			int v = in.range((w+1)*sizeof(int)*8-1, w*sizeof(int)*8).to_int();
			csum[w + NINT*i] += v;
		}

	}
}

Perhaps XRTis confused because the xclbininfo shows the incorrect signature

Signature: read_pointer_sum2 (void* pin, unsigned int nread, int* nzero, int* csum_0)

see the sum.xclbin in the attached zip file, which can be made with

test_lut.zip

Вопрос:

В ядре 2.6.11.5 делить нулевой обработчик исключений устанавливается как:

set_trap_gate(0,&divide_error);

В соответствии с “Понимание ядра Linux” доступ к ловушке Intel невозможен с помощью процесса пользовательского режима. Но вполне возможно, что процесс пользовательского режима также генерирует divide_error. Так почему Linux реализует его таким образом?

[Изменить]
Я думаю, что вопрос все еще открыт, так как set_trap_gate() устанавливает значение DPL записи IDT равным 0, что означает, что код CPL = 0 (read kernel) может его выполнить, поэтому мне непонятно, как этот обработчик может быть вызван из пользовательский режим:

#include<stdio.h>

int main(void)
{
int a = 0;
int b = 1;

b = b/a;

return b;
}

который был скомпилирован с помощью gcc div0.c. Результат ./a.out:

Исключение с плавающей запятой (сбрасывание ядра)

Таким образом, это не выглядит так, как это было обработано кодом деления на 0.

Ответ №1

У меня есть источники ядра Linux 3.7.1 на руках, и из-за этого я попытаюсь дать ответ на ваш вопрос на основе этих источников. Что мы имеем в коде. В archx86kerneltraps.c мы имеем функцию early_trap_init(), где можно найти следующую строку кода:

set_intr_gate(X86_TRAP_DE, &divide_error);

Как мы можем видеть, set_trap_gate() был заменен на set_intr_gate(). Если в следующем повороте мы расширим этот вызов, мы добьемся:

_set_gate(X86_TRAP_DE, GATE_INTERRUPT, &divide_error, 0, 0, __KERNEL_CS);

_set_gate – это подпрограмма, которая отвечает за две вещи:

  • Построение дескриптора IDT
  • Установка сконструированного дескриптора в целевую ячейку в
    массив дескрипторов IDT. Второй – это просто копирование памяти и
    нам неинтересно. Но если мы посмотрим, как он конструирует
    дескриптора из поставляемых параметров мы увидим:

    struct desc_struct{
    unsigned int a;
    unsigned int b;
    };
    
    desc_struct gate;
    
    gate->a = (__KERNEL_CS << 16) | (&divide_error & 0xffff);
    gate->b = (&divide_error & 0xffff0000) | (((0x80 | GATE_INTERRUPT | (0 << 5)) & 0xff) << 8);
    

Или, наконец,

gate->a = (__KERNEL_CS << 16) | (&divide_error & 0xffff);
gate->b = (&divide_error & 0xffff0000) | (((0x80 | 0xE | (0 << 5)) & 0xff) << 8);

Как мы увидим в конце конструкции дескриптора, мы будем иметь следующую структуру данных из 8 байтов в памяти

[0xXXXXYYYY][0xYYYY8E00], where X denotes digits of kernel code segment selector number, and Y denotes digits of address of the divide_error routine.

Эти 8-байтовые структуры данных представляют собой дескриптор прерываний, определенный процессором. Он используется процессором для определения того, какие действия необходимо предпринять в ответ на прием прерывания с определенным вектором. Теперь посмотрим на формат дескриптора прерываний, определенный семейством процессоров Intel для x86:

                              80386 INTERRUPT GATE
31                23                15                7                0
+-----------------+-----------------+---+---+---------+-----+-----------+
|           OFFSET 31..16           | P |DPL|  TYPE   |0 0 0|(NOT USED) |4
|-----------------------------------+---+---+---------+-----+-----------|
|             SELECTOR              |           OFFSET 15..0            |0
+-----------------+-----------------+-----------------+-----------------+

В этом формате пара SELECTOR: OFFSET определяет адрес функции (в длинном формате), который будет принимать управление в ответ на прием прерывания. В нашем случае это __KERNEL_CS:divide_error, где divide_error() является фактическим обработчиком исключения Division By Zero.
P указывает, что дескриптор следует рассматривать как допустимый дескриптор, который был правильно настроен ОС, и в нашем случае он в повышенном состоянии.
DPL – укажите защитные кольца, на которых функция divide_error() может быть запущена с помощью мягких прерываний. Некоторый фон должен был понять роль этой области.

В общем случае существует три типа источников прерываний:

  • Внешнее устройство, запрашивающее службу из ОС.
  • Сам процессор, когда обнаружил, что он получает доход в ненормальное состояние
    запрашивая ОС, чтобы помочь ей выйти из этого состояния.
  • Выполняется программа на процессоре под управлением ОС, которая запрашивает у нее специальную службу.

Последний случай имеет специальную поддержку от процессора в виде выделенной команды int XX. Каждый раз, когда программе требуется служба ОС, она устанавливает параметры, описывающие запрос и выдачу команды int с параметром, который описывает вектор прерывания, который используется ОС для предоставления услуг. Прерывания, генерируемые выдачей команды int, называемой мягкими прерываниями. Таким образом, процессор учитывает поле DPL только тогда, когда он обрабатывает мягкие прерывания, полностью игнорирует их в случае прерываний, генерируемых самим процессором или внешними устройствами. DPL – очень важная функция, поскольку она запрещает приложениям имитировать устройства, и это подразумевает поведение системы.

Представьте себе, например, что какое-то приложение сделает что-то вроде этого:

for(;;){
__asm int 0xFF;

//where 0xFF is vector used by system timer, to notify the kernel that the
another one timer tick was occurred
}

В этом случае время на вашем компьютере будет намного быстрее, чем в реальной жизни, тогда вы ожидаете, и ваша система ожидает. В результате ваша система будет очень плохо себя вести. Как вы можете видеть, процессор и внешние устройства считаются доверенными, но это не относится к приложениям пользовательского режима. В нашем случае исключения Division By Zero Linux указывает, что это исключение может быть вызвано мягким прерыванием только с кольца 0 или, другими словами, только из ядра. В результате, если команда int 0 будет выполнена в пространстве ядра, процессор передаст управление подпрограмме divide_error(). Если в пользовательском пространстве будет выполняться одна и та же инструкция, ядро ​​будет являться нарушением защиты и передаст управление обработчику исключений защиты от общих проблем (это действие по умолчанию для всех недействительных мягких прерываний). Но если исключение Division By Zero будет генерироваться самим процессором, попытка делить некоторое значение на ноль, управление будет передано в процедуру divide error(), независимо от места, где произошло неправильное деление.
В общем, похоже, что это не будет иметь большого вреда, чтобы приложение могло запускать триггерное разделение на исключение Zero с помощью мягкого прерывания. Но для первого это будет уродливый дизайн, а для второй может быть какая-то логика, которая зависит от того, что исключение Division By Zero может быть сгенерировано только посредством фактической неправильной операции деления.

Поле

TYPE указывает вспомогательные действия, которые должен выполняться процессором в ответ на прием прерывания. В реальной жизни используются только два типа дескрипторов исключений: дескриптор прерывания и дескриптор trap. Они отличаются только одним аспектом. Дескриптор прерывания заставляет процессор отключать прием будущих прерываний, а дескриптор trap не делает этого. Если честно, я не знал, почему ядро ​​Linux использует дескриптор прерывания для обработки исключений из раздела по Zero. Что касается меня, то здесь лучше подходит дескриптор ловушки.

И последнее примечание в отношении запутанного вывода тестовой программы

Floating point exception (core dumped)

По историческим причинам ядро ​​Linux отвечает на исключение Division By Zero, отправляя сигнал SIGFPE (чтение SIGnal Floating Point Exception) в процесс, пытающийся делить на ноль. Да, не SIGDBZ (читайте SIGnal Division By Zero). Я знаю, что это довольно запутанно. Причиной такого поведения является то, что Linux имитирует оригинальное поведение UNIX (я думаю, что это поведение было заморожено в POSIX) и в оригинальной UNIX, почему почему исключение “Division By Zero” используется как “исключение с плавающей запятой”. Я не знаю, почему.

Ответ №2

бит DPL в IDT рассматривается только тогда, когда программное прерывание вызывается с помощью инструкции int. Деление на ноль – это программное прерывание, инициируемое процессором, и поэтому DPL не имеет эффекта в этом случае.

Ответ №3

Код режима пользователя не имеет доступа к системным таблицам, например таблицы дескриптора сегмента и прерывания, они не предназначены для управления вне ядра ОС, и нет необходимости. Линукс-обработчики для исключений, такие как деление на ноль, исключение общей защиты, ошибка страницы и другие исключения перехвата, происходящие как из режима пользователя, так и из режима ядра. Они могут обрабатывать их по-разному на основе происхождения, но таблица дескрипторов прерываний содержит адрес только одного обработчика для каждого вида исключения (например, выше). И каждый обработчик знает, как обрабатывать его исключение.

Ответ №4

Ядро не работает в пользовательском режиме. Он должен обрабатывать ловушку, генерируемую программами пользовательского режима (например, процессы linux в пользовательской зоне). Кодекс ядра не должен делиться на ноль.

Я плохо понимаю ваш вопрос. Как бы вы реализовали это в противном случае?

Ответ №5

Ответ на часть вашего вопроса можно найти в Разделе 6.12.1.1 “Архиваторов Intel® и 64-х и IA-32”, том 3A “

Процессор проверяет DPL шлюза прерывания или ловушки только в том случае, если исключение или       прерывание генерируется с помощью инструкции INT n, INT 3 или INTO. Здесь CPL       должно быть меньше или равно DPL затвора. Это ограничение предотвращает       прикладные программы или процедуры, запущенные на уровне привилегий 3, с использованием       прерывание программного обеспечения для доступа к критическим обработчикам исключений, таким как ошибка страницы       обработчика, при условии, что эти обработчики помещаются в более привилегированный код       сегменты (с более низким уровнем привилегий). Для аппаратных прерываний       и обработанных процессором исключений, процессор игнорирует DPL прерывания       и ловушки.

Это то, что ответил Алекс Креймер

Относительно сообщения. Я не совсем уверен, но кажется, что ОС посылает сигнал SIGFPE в процесс.

Bug #1730027 reported by
Seth Arnold
on 2017-11-04

This bug affects 1 person

Affects Status Importance Assigned to Milestone


atop (Ubuntu)

New

Undecided


Unassigned

Bug Description

Hello, I have these messages in dmesg:

$ dmesg | grep atop
[862887.780279] traps: atop[5696] trap divide error ip:4073c2 sp:7ffc935b5780 error:0 in atop[400000+26000]
[1122069.716309] traps: atop[1648] trap divide error ip:4073c2 sp:7ffe1188f0c0 error:0 in atop[400000+26000]
[2158799.465616] traps: atop[10067] trap divide error ip:4073c2 sp:7ffdd6b7a170 error:0 in atop[400000+26000]
[3713893.433435] traps: atop[10827] trap divide error ip:4073c2 sp:7fffb6334710 error:0 in atop[400000+26000]
[4664228.402493] traps: atop[17078] trap divide error ip:4073c2 sp:7ffd9d9135d0 error:0 in atop[400000+26000]

Thanks

ProblemType: Bug
DistroRelease: Ubuntu 16.04
Package: atop 1.26-2build1
ProcVersionSignature: Ubuntu 4.4.0-87.110-generic 4.4.73
Uname: Linux 4.4.0-87-generic x86_64
NonfreeKernelModules: zfs zunicode zcommon znvpair zavl
ApportVersion: 2.20.1-0ubuntu2.10
Architecture: amd64
Date: Fri Nov 3 19:37:41 2017
InstallationDate: Installed on 2016-04-04 (578 days ago)
InstallationMedia: Ubuntu-Server 16.04 LTS «Xenial Xerus» — Beta amd64 (20160325)
ProcEnviron:
 TERM=screen
 PATH=(custom, no user)
 XDG_RUNTIME_DIR=<set>
 LANG=en_US.UTF-8
 SHELL=/bin/bash
SourcePackage: atop
UpgradeStatus: No upgrade log present (probably fresh install)

This document (3056441) is provided subject to the disclaimer at the end of this document.

Environment

SUSE Linux Enterprise Desktop 10 SP1
SUSE Linux Enterprise Server 10 SP1

Situation

When booting a SLE10 SP1 based system, an error message similar to the following is presented:

ERROR:parted[5683] trap divide error rip:2b0fe2e5f781 rsp:7fffc7d8c300 error:0

The message may appear with a different rip andrspvalue.

Resolution

This error does not harm the system in its functionality. parted may get called on multipath devices controlled by device mapper. Because those devices are no real devices, some ioctl  calls may return unexpected values and in return cause parted to crash.

Please update to

parted version 1.6.25.1-15.13 or later.

Disclaimer

This Support Knowledgebase provides a valuable tool for SUSE customers and parties interested in our products and solutions to acquire information, ideas and learn from one another. Materials are provided for informational, personal or non-commercial use within your organization and are presented «AS IS» WITHOUT WARRANTY OF ANY KIND.

  • Document ID:3056441
  • Creation Date:
    07-Mar-2008
  • Modified Date:23-Feb-2021
    • SUSE Linux Enterprise Desktop
    • SUSE Linux Enterprise Server

< Back to Support Search

For questions or concerns with the SUSE Knowledgebase please contact: tidfeedback[at]suse.com

Понравилась статья? Поделить с друзьями:
  • Transpress jcb 3cx ошибка
  • Trace error opening trace file no such file or directory
  • Transport vmdb error 14 pipe connection has been broken vmware
  • Transport loopywriter run returning connection error desc transport is closing
  • Transport level error while connecting to general error 0x502