Skip to content

Conversation

@AaronDot
Copy link
Contributor

@AaronDot AaronDot commented Feb 25, 2025

Add LoongArch security engine driver support

Summary by Sourcery

This pull request introduces support for the Loongson Security Engine (SE) in the Linux kernel. It includes drivers for the SE module itself and its Secure Data File (SDF) interface, along with necessary header files, device tree bindings, and build configurations. The drivers enable the use of hardware-accelerated cryptographic functions provided by the Loongson SE.

New Features:

  • Adds a driver for the Loongson Security Engine (SE) module, enabling hardware-accelerated cryptographic operations.
  • Adds a driver for the Loongson Security Engine (SE) Secure Data File (SDF) interface.

Enhancements:

  • Provides functions to initialize and deinitialize SE channels, and to send requests to them.

Build:

  • Adds Kconfig options and Makefile entries to build the Loongson SE and SDF drivers.

@sourcery-ai
Copy link

sourcery-ai bot commented Feb 25, 2025

Reviewer's Guide by Sourcery

This pull request introduces the LoongArch security engine driver, comprising a core driver (loongson_se.c) and an SDF character device driver (lsse_sdf_cdev.c). The core driver handles hardware initialization, interrupt management, and command processing, while the SDF driver exposes secure data functions to user space. Device tree bindings and a hardware register definition header are also included.

Sequence diagram for sending a command to the SE

sequenceDiagram
  participant User
  participant lsse_sdf_cdev.c
  participant lsse_sdf_dev
  participant lsse_ch
  participant loongson_se.c

  User->>lsse_sdf_cdev.c: write()
  lsse_sdf_cdev.c->>lsse_sdf_dev: lsse_sdf_send(buf, count, user)
  lsse_sdf_dev->>lsse_ch: se_send_ch_requeset(ch)
  lsse_ch->>loongson_se.c: se_send_ch_requeset(ch)
  loongson_se.c->>loongson_se.c: se_writel(int_bit, SE_L2SINT_SET)
  loongson_se.c-->>lsse_ch: Returns
  lsse_ch-->>lsse_sdf_dev: Returns
  lsse_sdf_dev-->>lsse_sdf_cdev.c: Returns
  lsse_sdf_cdev.c-->>User: Returns
Loading

Sequence diagram for SE interrupt handling

sequenceDiagram
  participant loongson_se.c
  participant lsse_ch

  loongson_se.c->>loongson_se.c: loongson_se_irq(irq, dev_id)
  alt int_status & SE_INT_SETUP
    loongson_se.c->>loongson_se.c: complete(&se->cmd_completion)
  else int_status & other interrupts
    loop for each interrupt
      loongson_se.c->>lsse_ch: ch->complete(ch)
      lsse_ch-->>loongson_se.c: Returns
    end
  end
  loongson_se.c-->>loongson_se.c: Returns
Loading

Class diagram for Loongson SE driver

classDiagram
  class loongson_se {
    -struct device *dev
    -void __iomem *base
    -u32 version
    -u32 ch_status
    -spinlock_t cmd_lock
    -spinlock_t dev_lock
    -void *mem_base
    -dma_addr_t mem_addr
    -unsigned long *mem_map
    -int mem_map_size
    -void *smsg
    -void *rmsg
    -struct completion cmd_completion
    -struct lsse_ch chs[SE_CH_MAX]
  }
  class lsse_ch {
    -u32 id
    -u32 int_bit
    -struct loongson_se *se
    -void *priv
    -spinlock_t ch_lock
    -void *smsg
    -void *rmsg
    -int msg_size
    -void *data_buffer
    -dma_addr_t data_addr
    -int data_size
    -void (*complete)(struct lsse_ch *se_ch)
  }
  loongson_se -- lsse_ch : contains
  note for loongson_se "Represents the Loongson Security Engine device."
  note for lsse_ch "Represents a channel within the Loongson Security Engine."
Loading

Class diagram for lsse_sdf_dev

classDiagram
  class lsse_sdf_dev {
    -struct lsse_ch *se_ch
    -struct mutex data_lock
    -bool processing_cmd
    -wait_queue_head_t wq
  }
  class lsse_ch
  lsse_sdf_dev -- lsse_ch : contains
  note for lsse_sdf_dev "Represents the Loongson SE SDF device."
Loading

File-Level Changes

Change Details Files
Added LoongArch security engine driver support, including the core driver and a character device driver for the SDF (Secure Data Function) functionality.
  • Added Kconfig and Makefile entries to build the drivers.
  • Implemented the core driver (loongson_se.c) to manage the SE hardware, including initialization, interrupt handling, command submission, and memory management.
  • Implemented the SDF character device driver (lsse_sdf_cdev.c) to provide a user-space interface for secure data functions.
  • Added a header file (asm/se.h) defining the register map and data structures for interacting with the SE hardware.
  • Added a device tree binding (se.yaml) for the Loongson SE module.
drivers/char/Makefile
drivers/char/Kconfig
drivers/char/loongson_se.c
drivers/char/lsse_sdf_cdev.c
arch/loongarch/include/asm/se.h
Documentation/devicetree/bindings/security/loongson_se/se.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot
Copy link

Hi @AaronDot. Thanks for your PR.

I'm waiting for a deepin-community member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @AaronDot - I've reviewed your changes - here's some feedback:

Overall Comments:

  • Consider adding a comment block at the beginning of each file describing its purpose.
  • It would be helpful to have some examples of how to use the new API.
Here's what I looked at during the review
  • 🟡 General issues: 1 issue found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

spin_unlock_irqrestore(&se->dev_lock, flag);
}

static int se_send_requeset(struct loongson_se *se,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (typo): Typo in function name: 'se_send_requeset' should be 'se_send_request'.

Correcting the spelling will improve clarity and consistency throughout the code.

Suggested change
static int se_send_requeset(struct loongson_se *se,
static int se_send_request(struct loongson_se *se,

wake_up(&se->wq);
}

static int se_send_sdf_cmd(struct lsse_sdf_dev *se, int len, int retry)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider improving code readability and maintainability by extracting retry logic into helper functions and reducing nested error handling.

Consider reducing the nested error handling and retry logic by extracting these behaviors into helper functions. For example:

  1. Extracting Retry Logic:
    Instead of embedding a label and goto in se_send_sdf_cmd(), create a helper function to handle the retry loop. This makes the logic self‐documenting and easier to maintain.

    static int send_cmd_with_retry(struct lsse_sdf_dev *se, int len, int retries)
    {
        int err = -EIO;  // or an appropriate error code
        while (retries-- > 0) {
            pr_debug("Send sdf cmd, remaining retries: %d\n", retries);
            err = se_send_ch_requeset(se->se_ch);
            if (!err)
                return 0;
            udelay(5);
        }
        return err;
    }

    Then update se_send_sdf_cmd():

    static int se_send_sdf_cmd(struct lsse_sdf_dev *se, int len, int retry)
    {
        struct se_sdf_msg *smsg = (struct se_sdf_msg *)se->se_ch->smsg;
        unsigned long flag;
        int err;
    
        spin_lock_irqsave(&se->se_ch->ch_lock, flag);
    
        smsg->cmd = SE_CMD_SDF;
        smsg->data_off = se->se_ch->data_buffer - se->se_ch->se->mem_base;
        smsg->data_len = len;
    
        err = send_cmd_with_retry(se, len, retry);
    
        spin_unlock_irqrestore(&se->se_ch->ch_lock, flag);
        return err;
    }
  2. Streamlining Error Paths:
    In functions like lsse_sdf_send() and lsse_sdf_recv(), try to reduce deep nesting by returning early when an error occurs. This helps flatten the control flow and improves readability. For instance, refactor as:

    static int lsse_sdf_send(struct sdf_file_pvt_data *pvt, const char *buf,
                                size_t count, int user)
    {
        int ret, se_ret;
        struct sdf_handle *ph = NULL;
        struct sdf_kernel_command *skc;
        struct lsse_sdf_dev *se = pvt->se;
    
        if (!se->se_ch->smsg) {
            pr_err("se device is not ready\n");
            return 0;
        }
        if (count > se->se_ch->data_size) {
            pr_err("Invalid size in send: count=%zd, size=%d\n", count, se->se_ch->data_size);
            return -EIO;
        }
    
        ret = user ? mutex_lock_interruptible(&se->data_lock) : (mutex_lock(&se->data_lock), 0);
        if (ret)
            return ret;
    
        if (user) {
            ret = copy_from_user(se->se_ch->data_buffer, buf, count);
            if (ret) {
                ret = -EFAULT;
                goto out_unlock;
            }
            skc = (struct sdf_kernel_command *)se->se_ch->data_buffer;
            if (skc->header.command == SDF_OPENSESSION)
                ph = find_sdf_handle(skc->handle, pvt);
        } else {
            memcpy(se->se_ch->data_buffer, buf, count);
        }
    
        se->processing_cmd = true;
        ret = se_send_sdf_cmd(se, count, 5);
        if (ret) {
            pr_err("se_send_sdf_cmd failed\n");
            goto out_unlock;
        }
    
        ret = lsse_sdf_recv(pvt, (char *)buf, 0, user, &se_ret);
        if (ret) {
            pr_err("recv failed ret: %x\n", ret);
            goto out_unlock;
        }
        if (ph && !se_ret) {
            list_del(&ph->handle_list);
            kfree(ph);
        }
    out_unlock:
        mutex_unlock(&se->data_lock);
        return ret;
    }

These small changes help isolate specific concerns (retry logic, error handling) and flatten nested conditions while keeping the original functionality intact.

@AaronDot
Copy link
Contributor Author

Fix typo

Signed-off-by: Hongchen Zhang <zhanghongchen@loongson.cn>
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
Signed-off-by: Zhao Qunqin <zhaoqunqin@loongson.cn>
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
@AaronDot
Copy link
Contributor Author

Fix typo: se_send_ch_requeset -> se_send_ch_request

@AaronDot AaronDot reopened this Feb 25, 2025
Copy link
Member

@opsiff opsiff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm
/ok-to-test

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: opsiff, sourcery-ai[bot]

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@opsiff opsiff merged commit 1080858 into deepin-community:linux-6.6.y Feb 25, 2025
6 of 9 checks passed
@AaronDot AaronDot deleted the se-6.6 branch May 7, 2025 08:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants